Forum » Programiranje » T-SQL FIRST / TOP / MAX...
T-SQL FIRST / TOP / MAX...

nurmaln ::
Imam sledeč problemčič:
Artikel | Line No. | Text
000001 | 1 | Opis 1
000001 | 2 | Opis 2
000001 | 4 | Opis 3
000001 | 7 | Opis 4
000002 | 1 | Opis 1
000002 | 4 | Opis 2
000002 | 8 | Opis 3
000002 | 22 | Opis 4
Za izpis opisov posameznega artikla dam pač SELECT... WHERE Artikel = 000001 ORDER BY Line No
Potreboval bi pa izpis:
Artikel | Opis 1 | Opis 2 | Opis 3 |...
kakšna ideja?
Pudaril bi rad samo dejstvo, da Line No_ si sicer sledijo od njmanjšega do največjega ampak vmes je lahko večja razlika kot samo 1 (prikazano tudi zgoraj)
Artikel | Line No. | Text
000001 | 1 | Opis 1
000001 | 2 | Opis 2
000001 | 4 | Opis 3
000001 | 7 | Opis 4
000002 | 1 | Opis 1
000002 | 4 | Opis 2
000002 | 8 | Opis 3
000002 | 22 | Opis 4
Za izpis opisov posameznega artikla dam pač SELECT... WHERE Artikel = 000001 ORDER BY Line No
Potreboval bi pa izpis:
Artikel | Opis 1 | Opis 2 | Opis 3 |...
kakšna ideja?
Pudaril bi rad samo dejstvo, da Line No_ si sicer sledijo od njmanjšega do največjega ampak vmes je lahko večja razlika kot samo 1 (prikazano tudi zgoraj)

zigi ::
Ti bi rad dobil ven toliko stolpcev kot je različnih opisov, ali bi rad dal vse opise za določen artikel v en stolpec skupaj?

nurmaln ::
Pravzaprav bi mi koristili obe varjanti. Ampak če jih spravim v ločene stolpce, jih potem ni poseben problem še združiti v enega.

Microsoft ::
Hm, ce bo pomagalo:
SELECT DISTINCT [Text] FROM dbo.Table WHERE [Artikel] = '00000001'
Sicer je pa obracanje s PIVOT funkcijo malo tezje, ker aggregate functions ne delajo najbolje na stringu...
by Miha
SELECT DISTINCT [Text] FROM dbo.Table WHERE [Artikel] = '00000001'
Sicer je pa obracanje s PIVOT funkcijo malo tezje, ker aggregate functions ne delajo najbolje na stringu...
by Miha
s8eqaWrumatu*h-+r5wre3$ev_pheNeyut#VUbraS@e2$u5ESwE67&uhukuCh3pr

kopernik ::
Opisano težavo bi jaz rešil kar v aplikaciji in ne s poizvedbo na bazo (najbrž bi moral napisati kar stored proceduro, ker ne vem če je rešitev možna s standardnim sql). Se pravi, da bi naredil iteracijo čez rezultate in "ročno" zložil vse tekste v enega.

zigi ::
Dosti ljudi pravi 'cursors are bad for you', tu pa imaš primer vgnezdenega kurzorja
Recimo da imaš tabelo _tabela(artikel, naziv). Rezultat pa dobiš v tabeli ##temp.

Recimo da imaš tabelo _tabela(artikel, naziv). Rezultat pa dobiš v tabeli ##temp.
if exists (select 1 from tempdb..sysobjects where name = '##temp')
drop table ##temp
go
create table ##temp (artikel varchar(16))
go
--tukaj dobiš največje število opisov, da lahko dodaš ustrezno število stolpcev svoji novi tabeli
declare @stOpisov int
select @stOpisov = max(stOpisov)
from (
select distinct artikel, count(1) stOpisov
from _tabela
group by artikel
) k
declare @i int, @imeStolpca sysname, @ukaz varchar(1024)
set @i = 1
while @i <= @stOpisov
begin
set @imeStolpca = 'Opis' + convert(varchar, @i)
set @ukaz = 'alter table ##temp add ' + @imeStolpca + ' varchar(255)'
exec(@ukaz)
set @i = @i + 1
end
insert into ##temp (artikel) select distinct artikel from _tabela order by artikel
--ko imaš narejeno novo tabelo, vneseš podatke
declare @artikel varchar(16), @naziv varchar(40), @artikelStari varchar(16)
set @i = 0
set @artikelStari = (select top 1 artikel from _tabela order by artikel)
declare c cursor local fast_forward for
select distinct artikel
from _tabela
order by artikel
open c
fetch next from c into @artikel
while @@fetch_status = 0
begin
declare d cursor local fast_forward for
select naziv
from _tabela
where artikel = @artikel
order by naziv
open d
fetch next from d into @naziv
while @@fetch_status = 0
begin
if @artikel <> @artikelStari
set @i = 1
else
set @i = @i + 1
set @imeStolpca = 'Opis' + convert(varchar, @i)
set @ukaz = 'update ##temp set ' + @imeStolpca + ' = ''' + @naziv + ''' where artikel = ''' + @artikel + ''''
exec(@ukaz)
set @artikelStari = @artikel
fetch next from d into @naziv
end
close d
deallocate d
fetch next from c into @artikel
end
close c
deallocate c
Zgodovina sprememb…
- spremenil: zigi ()

frudi ::
Ali je število opisov enako pri vseh artiklih? V tem primeru bi lahko uporabil dosti enostavnejšo rešitev. Ampak predvidevam, da ni, sicer bi imel tabelo s stolpci Text1, Text2, Text3.
Se pa sicer strinjam s kopernikom - takšne probleme, če je le možno, raje rešuj v aplikaciji, ne na bazi.
Če pa že hočeš po vsej sili to počet na bazi, pa je tule še ena rešitev brez kurzorjev. Sicer vsebuje eno WHILE zanko, ampak ta vsaj vsebuje le toliko korakov, kolikor je max. število opisov za posamezni artikel. Ta rešitev je tudi brez dinamičnih SQL stavkov in globalnih začasnih tabel, tako da se procedura ne bi smela vedno znova prevajat ob klicu. Dobiš pa na koncu že sestavljen opis za posamezni artikel. Če bi želel vsak opis v svojem stolpcu, je potrebna še kr precejšnja sprememba. Povej, če to nujno potrebuješ, pa se mogoče spravim dodat še to...
Se pa sicer strinjam s kopernikom - takšne probleme, če je le možno, raje rešuj v aplikaciji, ne na bazi.
Če pa že hočeš po vsej sili to počet na bazi, pa je tule še ena rešitev brez kurzorjev. Sicer vsebuje eno WHILE zanko, ampak ta vsaj vsebuje le toliko korakov, kolikor je max. število opisov za posamezni artikel. Ta rešitev je tudi brez dinamičnih SQL stavkov in globalnih začasnih tabel, tako da se procedura ne bi smela vedno znova prevajat ob klicu. Dobiš pa na koncu že sestavljen opis za posamezni artikel. Če bi želel vsak opis v svojem stolpcu, je potrebna še kr precejšnja sprememba. Povej, če to nujno potrebuješ, pa se mogoče spravim dodat še to...
-- začasna tabela za rezultat
IF EXISTS(SELECT * FROM tempdb.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '#ArtTemp%')
DROP TABLE #ArtTemp
CREATE TABLE #ArtTemp(
Artikel NVARCHAR(8) NOT NULL,
[Line No.] INT NOT NULL,
[Text] NVARCHAR(100) NULL)
-- v začasno tabelo shranimo Artikle in njihov najmanjši Line No.
INSERT INTO #ArtTemp (Artikel, [Line No.])
SELECT Artikel, MIN([Line No.])
FROM _tabela
GROUP BY Artikel
-- v začasno tabelo dodamo še 1. opis
UPDATE #ArtTemp
SET #ArtTemp.[Text] = A.[Text]
FROM _tabela AS A
WHERE #ArtTemp.Artikel = A.Artikel AND #ArtTemp.[Line No.] = A.[Line No.]
-- spremenljivki za iteracijo
DECLARE @i INT
DECLARE @colCount INT
-- max število opisov za posamezni artikel
SET @i = 1
SELECT @colCount = MAX(OPIS_COUNT)
FROM (SELECT Artikel, COUNT([Text]) AS OPIS_COUNT FROM _tabela GROUP BY Artikel) AS X
-- prištejmo še ostale opise...
WHILE @i < @colCount BEGIN
-- najprej označimo tiste artikle, ki eventualno več nimajo nobenega opisa (nastavimo jim Line No. na -1; lahko bi tudi drugače...)
-- to preverimo tako, da preverimo, če obstaja še kak zapis z enakim Artikel in večjim Line No.
UPDATE #ArtTemp
SET #ArtTemp.[Line No.] = -1
WHERE NOT EXISTS(
SELECT NULL
FROM _tabela AS A
WHERE #ArtTemp.Artikel = A.Artikel AND #ArtTemp.[Line No.] < A.[Line No.])
-- Line No. v začasni tabeli postavimo na naslednji najnižji Line No. izmed preostalih zapisov
UPDATE #ArtTemp
SET #ArtTemp.[Line No.] = X.MIN_LINE_NO
FROM (SELECT Artikel, MIN([Line No.]) AS MIN_LINE_NO
FROM _tabela AS A
WHERE NOT EXISTS( -- tale pogoj izloči že dodane opise (* skupaj s pogojem za Line No. > -1)
SELECT NULL
FROM #ArtTemp AS T
WHERE A.Artikel = T.Artikel AND A.[Line No.] <= T.[Line No.])
GROUP BY Artikel) AS X
WHERE #ArtTemp.Artikel = X.Artikel AND #ArtTemp.[Line No.] > -1 -- * (glej opombo par vrstic višje...)
-- v začasno tabelo 'prištejemo' še opise prej določenih naslednjih najnižjih Line No.
UPDATE #ArtTemp
SET #ArtTemp.[Text] = #ArtTemp.[Text] + ' ' + A.[Text]
FROM _tabela AS A
WHERE #ArtTemp.Artikel = A.Artikel AND #ArtTemp.[Line No.] = A.[Line No.]
-- d0h...
SET @i = @i + 1
END
-- preverimo rezultat
SELECT Artikel, [Text]
FROM #ArtTemp
1ACDoHVj3wn7N4EMpGVU4YGLR9HTfkNhTd... in case I've written something useful :)
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | [SQL] Pohitritev izpisaOddelek: Programiranje | 3177 (2076) | kuall |
» | PostgreSQL pomočOddelek: Programiranje | 2614 (2107) | Mato989 |
» | [SQL] Unikatni izpisiOddelek: Programiranje | 2337 (1724) | 111111111111 |
» | T-SQL preprost querry pa ne znamOddelek: Programiranje | 1901 (1558) | borchi |
» | [delphi] 2 bazi v eni mrežiOddelek: Programiranje | 1221 (1170) | seawolf |