Avatar billede entracore Nybegynder
26. oktober 2001 - 22:11 Der er 41 kommentarer og
2 løsninger

Sorter i en tabel

Hej

Jeg har et mindre problem, eller rettere stort, synes jeg. Jeg har en tabel indeholdende kolonnerne ID(Int), SubID(Int) og Vaerdi(Varchar).

SubID\'et er en relation til ID\'et.

F.eks.

#    ID    SubID    Vaerdi
-----------------------------
1      1      0        var001
2      2      0        var002
3      3      0        var003
4      4      2        var004
5      5      2        var005
6      6      5        var006
7      7      5        var007
Osv.....


Dvs at SubID\'et i række 4 og 5 har en forældre der hedder ID 2 og række 6 og 7 har en forældre der hedder ID 5.

Mit problem er så at jeg gerne vil have sorteret ovenstående tabel så rækker står således her:

#    ID    SubID    Vaerdi
-----------------------------
1      1      0        var001
2      2      0        var002
3      4      2        var004
4      5      2        var005
5      6      5        var006
6      7      5        var007
7      3      0        var003

Så at alle SubID\'erne med en værdi står under det ID der har værdien og i den dur.

Hvordan strikker jeg sådan en SQL sætning frem.

Hvis der er spørgsmål i forbindelse med dette - så bare spørg løs.

På forhånd tak.
Avatar billede entracore Nybegynder
26. oktober 2001 - 22:16 #1
Jeg har selvfølgelig glemt at nævne at SQL strengen skal strikkes sammen i en Stored Procedure :)
Avatar billede dfens Nybegynder
27. oktober 2001 - 08:43 #2
Select * From Table Group By SubID
Avatar billede terry Ekspert
27. oktober 2001 - 10:39 #3
NOT understood! Why should ID3 subID0 come last?
Avatar billede terry Ekspert
27. oktober 2001 - 10:41 #4
Is it because there is only one record? If that sthe case then I think you should concider re-designing your table
Avatar billede dfens Nybegynder
27. oktober 2001 - 10:42 #5
youve got a point
Avatar billede entracore Nybegynder
27. oktober 2001 - 13:42 #6
Terry >> The reason ID3/SubID0 comes last is because it has no children.

Re-designing my table??? If there is any suggestions I\'ll welcome them.
Avatar billede terry Ekspert
27. oktober 2001 - 17:00 #7
But niether has ID 1 and 2?
Avatar billede terry Ekspert
28. oktober 2001 - 11:15 #8
SELECT ID, SubID
FROM YourTable
ORDER BY IIf([SubID]=0,1,0),ID
Avatar billede terry Ekspert
28. oktober 2001 - 11:16 #9
But thsi move ALL those with 0 in SubID to the ned of the list, I am guessing that this is what you want!
Avatar billede lkp Nybegynder
29. oktober 2001 - 16:40 #10
Hej Entracore

Er det ikke nedenstående rækkefølge du er ude efter?


-Output Start---------------------
ID          SubID      Vaerdi   
----------- ----------- ----------
1          0          var001   
2          0          var002   
4          2          var004   
5          2          var005   
3          0          var003   
6          5          var006   
7          5          var007   
-Output Slut----------------------


Række med værdi ID=3 Skal vel sorteres efter række med ID=2 + evt. under kategorier. Ellers burde rækken med ID=1 vel også sorteres efter alle rækker med underkategorier.

Men hvis ovenstående output er OK kan nedenstående erklæring af en Stored Procedure anvendes:

-Procedure Start----------------------------
CREATE PROCEDURE procGetWeirdOrder AS

SELECT  ID, SubID, Vaerdi
FROM tblEks126051
ORDER BY ISNULL(NULLIF(SubID, 0), ID), subID
-Procedure Slut-----------------------------

Med venlig hilsen

LKP

terry > Is IIF valid in T-SQL?
Avatar billede terry Ekspert
29. oktober 2001 - 19:22 #11
lkp>As far as I can see it is

entracore>how about comming with your suggestions so we dont waist time?
Avatar billede entracore Nybegynder
29. oktober 2001 - 22:09 #12
lkp>> Din SQL streng generere det samme output som ved f.eks. bare at skrive select * from tblEks126051.

Jeg har forsøgt mig med nested sets men uden held desværre.
Avatar billede lkp Nybegynder
29. oktober 2001 - 23:13 #13
Hej Entracore

Ikke på min SQL server!

SQL: SELECT * FROM tblEks126051
-Output Start---------------------
ID          SubID      Vaerdi   
----------- ----------- ----------
1          0          var001   
2          0          var002   
3          0          var003   
4          2          var004   
5          2          var005   
6          5          var006   
7          5          var007   
-Output Slut----------------------

Altså det samme som den oprindelige tabel.

SQL:
SELECT  ID, SubID, Vaerdi
FROM tblEks126051
ORDER BY ISNULL(NULLIF(SubID, 0), ID), subID
-Output Start---------------------
ID          SubID      Vaerdi   
----------- ----------- ----------
1          0          var001   
2          0          var002   
4          2          var004   
5          2          var005   
3          0          var003   
6          5          var006   
7          5          var007
-Output Slut----------------------

Det er ikke helt det samme, er du sikker på at du har ændret feltnavne mv. så de passer til din tabel?

Med venlig hilsen

LKP
Avatar billede lkp Nybegynder
29. oktober 2001 - 23:19 #14
Hmmm... rødmer lidt

Selvom det ikke er det samme, er det ikke sikkert det er rigtigt. Det går først op for mig nu hvorfor ID=3 skal nederst.

Prøver lige igen i morgen hvis det er OK.

Med venlig hilsen

LKP
Avatar billede entracore Nybegynder
29. oktober 2001 - 23:24 #15
Det er bare iorden LKP :)
Avatar billede terry Ekspert
30. oktober 2001 - 08:06 #16
entracore>How about commenting the answers/comments given so far so we know what you expect? We cant help you if you dont participate yourself!
Avatar billede entracore Nybegynder
30. oktober 2001 - 19:20 #17
terry>> Reelt nok!

Min problematik består i at sortere en tabel.
Værdien i kolonnen SubID skal sorteres ud fra ID\'et, så ID\'et kommer først og dernæst dets børn, dvs SubID\'erne.
F.eks følgende tabel(Ikke sorteret):

ID    SubID
------------
1      0
2      0
3      1
4      1
5      1
6      4
7      4
8      7
9      7

Bliver sorteret så SubID\'erne er listet således her:

ID    SubID
------------
1      0
3      1
4      1
6      4
7      4
8      7
9      7
5      1
2      0

Jeg kan ikke rigtig komme med en bedre forklaring en ovenstående. Håber det er tilstrækkelig. :)
Avatar billede terry Ekspert
30. oktober 2001 - 19:56 #18
entracore> Sorry, I just cant get my head round this one!
I can not see wht ID 1 SubID 0 should be first, but 2 0 is last

Try and explain for each record why it should end up where it does. If I cant get a LOGICAL explanation then I cant give you an SQL statement!
Avatar billede entracore Nybegynder
30. oktober 2001 - 20:14 #19
Terry>> Ok I\'ll try and give you the best explanation I can,

ID    SubID
-----------
1      0  // (ID 1, SubID 0) is first because SubID has no parents.
3      1  // (ID 3, SubID 1) comes next because it has ID 1 as a parent. The value of the SubID indicate parent relationship.
4      1  // (ID 4, SubID 1) has ID 1 as a parent
6      4  // (ID 6, SubID 4) has ID 4 as a parent
7      4  // (ID 7, SubID 4) has ID 4 as a parent
8      7  // (ID 8, SubID 7) has ID 7 as a parent
9      7  // (ID 9, SubID 7) has ID 7 as a parent
5      1  // (ID 5, SubID 1) has ID 1 as a parent
2      0  // (ID 2, SubID 0) has no parent

Perhabs this illustration will be helpfull.

ID    SubID
------------
1      0
  3      1
  4      1
    6      4
    7      4
      8      7
      9      7
  5      1
2      0

Best Regards.
Avatar billede terry Ekspert
30. oktober 2001 - 20:29 #20
so ID 5 SubID 1 should come before 6-4?


Avatar billede entracore Nybegynder
30. oktober 2001 - 20:48 #21
No! Consider the table structure as a men on a webpage. For example you have
the following menu:

- Menu1
  - SubMenu1 To Menu1
  - SubMenu2 To Menu1
  - SubMenu3 To Menu1
      - SubSubMenu1 To SubMenu3
      - SubSubMenu2 To SubMenu3
        - SubSubSubMenu1 To SubSubMenu2
        - SubSubSubMenu2 To SubSubMenu2
  - Submenu4 To 1
- Menu2
- Menu3
Avatar billede terry Ekspert
30. oktober 2001 - 20:53 #22
entracore> I havent given up yet (almost) but I think I will need some time to think. Will get back when I have an answer or when I give up (never have yet but there is always a first time)
Avatar billede entracore Nybegynder
30. oktober 2001 - 20:58 #23
Thanks ;)
Avatar billede lkp Nybegynder
30. oktober 2001 - 23:17 #24
Hej Entracore

Jeg har heller ikke givet op, men har lige brug for en aften mere.

Håer du kan have tålmodighed lidt endnu :-)

Med venlig hilsen

LKP
Avatar billede entracore Nybegynder
31. oktober 2001 - 08:11 #25
LKP>> Fedest ;)
Avatar billede terry Ekspert
31. oktober 2001 - 09:15 #26
entracore>I can see EXACTLY what you want. Your menu diagram helped the bricks fall in place.

Problem is how to do it in SQL!
Which version of SQL are you using? I think it will be necessary to make a function and its not so easy in 7.0. Things are easier in 2000 but I dont have that installed!!!

I have actually solved this in Access by making a temp table.
Where are you using this, in ASP or VB. Perhaps some of the work could be done there?


Avatar billede terry Ekspert
31. oktober 2001 - 09:18 #27
Oh! just noticed the points increase, I feel like a donkey! (æsel)
Avatar billede entracore Nybegynder
31. oktober 2001 - 13:43 #28
I use SQL 2000. I would prefer to make it in a stored procedure. because of the performance issue.
Why do you feel like a donkey???
Avatar billede terry Ekspert
31. oktober 2001 - 13:45 #29
Increasing the points (bigger carrot!!!)
Avatar billede terry Ekspert
31. oktober 2001 - 13:46 #30
Do you use VB or ASP or something else?
Avatar billede entracore Nybegynder
31. oktober 2001 - 13:48 #31
I use ASP.
Avatar billede terry Ekspert
31. oktober 2001 - 13:57 #32
Ok!
what do you intend to use it for, your menu?
How many records do you expect in the tabel. If it was done in VBScript and not many records then you shouldnt have any performance problems.

As I have said, I dont think it can be done with a single SQL statement. As far as I can see there has to be a recursive call to a function to traverse into each (menu) adding each element on the way. This could be done in a Function in SQL Server (if it allows recursive calls) As you may well know a recursive call is a function which calls its self. It could also be done in your ASP (VBCript).



Avatar billede entracore Nybegynder
31. oktober 2001 - 14:05 #33
I except up 40 or 50 records in my table. I would prefer a Function in SQL. But is that necessary?
Couldn\'t it be done using a Cursor or a Loop in my Stored Procedure?
Avatar billede terry Ekspert
31. oktober 2001 - 14:37 #34
I have never used a cursor so I couldnt say.

As far as I can make out you WILL need a recursive function call to travers into the children of each item.
Avatar billede terry Ekspert
31. oktober 2001 - 15:25 #35
entracore> Do you have Access on your PC and if so do you know how to use it?

I can send you a little \"demo\" so you can maybe see why it snecessaryy to have a recursive call.
You can use the debugger and step through the program to see exactly what is happening.
Avatar billede entracore Nybegynder
31. oktober 2001 - 15:36 #36
Yes i have Access installed. You can send your demo to jg@parnell.dk.
thx. :)
Avatar billede lkp Nybegynder
31. oktober 2001 - 18:11 #37
Hej Entracore

Så tror jeg endelig den er der.

Løsningen er rekursiv, og jeg har implementeret den med 3 stored procedures.

Procedure du skal kalde fra din kode:

-Procedure Start------------------------------------------------------------
CREATE PROCEDURE procEks126051Main AS

    SET NOCOUNT ON

    DECLARE @tempTableName VARCHAR(64)
    DECLARE @sqlStatement NVARCHAR(1024)

    BEGIN TRANSACTION
   
    SET @tempTableName = \'##tempTable\' + CONVERT( VARCHAR(4), @@SPID )
    SET @sqlStatement = \'CREATE TABLE \' + @tempTableName
                        + \' (\'
                        + \'ID INT, \'
                        + \'subID INT, \'
                        + \'vaerdi NVARCHAR(25)\'
                        +\' )\'

    EXECUTE sp_executesql @sqlStatement

    EXECUTE procEks126051Build 0, @tempTableName
   
    SET @sqlStatement = \'SELECT * FROM \' + @tempTableName

    EXECUTE sp_executesql @sqlStatement

    SET @sqlStatement = \'DROP TABLE \' + @tempTableName

    EXECUTE sp_executesql @sqlStatement

    COMMIT TRANSACTION

    RETURN
-Procedure Slut-------------------------------------------------------------

Hjælpeprocedurer:

-Procedure Start------------------------------------------------------------
CREATE PROCEDURE procEks126051Build
(
    @parentID INT,
    @temptablename VARCHAR(64)
)
AS
    SET NOCOUNT ON
   
    DECLARE @ID INT
    DECLARE @subID INT
    DECLARE @vaerdi NVARCHAR(25)

    DECLARE @sqlStatement NVARCHAR(1024)

    DECLARE  @subListCursor CURSOR

    EXECUTE procEks126051Sub @parentID, @subListCursor OUTPUT

    WHILE( 1 = 1 )
    BEGIN
        FETCH NEXT FROM @subListCursor
        INTO  @ID, @subID, @vaerdi

        IF @@FETCH_STATUS = -1
            BREAK


        SET @sqlStatement = \'INSERT INTO \' + @temptablename
                    + \' VALUES(\'
                    + CONVERT( VARCHAR, @ID )
                    +\', \'
                    +CONVERT( VARCHAR, @subID )
                    +\', \' + \'\'\'\' + @vaerdi + \'\'\'\' + \')\'

        EXECUTE sp_executesql @sqlStatement

        EXECUTE procEks126051Build @ID, @temptablename
    END

    CLOSE @subListCursor

    DEALLOCATE @subListCursor
-Procedure Slut-------------------------------------------------------------

-Procedure Start------------------------------------------------------------
CREATE PROCEDURE procEks126051Sub
(
    @parentID INT,
    @subCursor CURSOR VARYING OUTPUT
)
AS
    SET NOCOUNT ON
   
    --!! HER SKAL DU ÆNDRE TABELNAVN !!--
    SET @subCursor = CURSOR FOR
        SELECT ID, subID, vaerdi
        FROM tblEks126051
        WHERE( @parentID <> 0 AND tblEks126051.subID = @parentID ) OR
            ( @parentID = 0 AND tblEks126051.subID = 0)
        ORDER BY ID

    OPEN @subCursor

    RETURN
-Procedure Slut-------------------------------------------------------------

Hvis din tabel har den struktur og de variabel typer du nævnte i det oprindelige spørgsmål, kan du bruge koden direkte hvis du blot ændrer tabelnavnet (jeg har angivet med en kommentar hvor).

Ellers kan du selv se om du kan finde de korrekte variable der skal skiftes, ellers kan du lige skrive med den rigtige tabeldefinition.

Jeg har regnet med værdi feltet som NVARCHAR(25).

Med venlig hilsen

LKP
Avatar billede entracore Nybegynder
31. oktober 2001 - 18:50 #38
Shit mand.... tak :)
Jeg implementer det lige og vender tilbage.
Avatar billede entracore Nybegynder
31. oktober 2001 - 19:30 #39
LKP >>Det er fandme for godt til at være sandt. Det virker fandme. Mange mange tak.

Vil det være iorden at jeg gav Terry 100 point ud af de 520 point, da han også har gjort et helvedes arbejde....
Avatar billede lkp Nybegynder
31. oktober 2001 - 19:33 #40
Hej Entracore

Det var godt :-)

Det er helt i orden at give Terry en del af pointene for hans store arbejde. Det var en hård nød at knække!

Med venlig hilsen

LKP
Avatar billede terry Ekspert
31. oktober 2001 - 19:44 #41
Mange tak for pointene:o)

LKP> I was usre I had made a comment earlier this evening, but it isnt to be seen.
Anyway, it saves me having to install SQL. How do you call this from say VB or even ASP?
Avatar billede lkp Nybegynder
31. oktober 2001 - 19:51 #42
Hej Terry

Eftersom den main proceduren ikke returnerer nogen værdier (ud over selvfølgelig en cursor(recordset)), kan du uden videre kalde den med execute kommandoen for en connection.

Var det det du mente?

Entracore>> Også et stort tak for de mange point herfra

Med venlig hilsen

LKP

PS Terry> Is it OK to answer you in Danish?
Avatar billede terry Ekspert
31. oktober 2001 - 19:55 #43
LKP>Ingen problem, jeg kan godt skrive på dansk (efter 18 år) men det er MEGET nemmere på engelsk :o)

Ja, det var det jeg mente!
Igen tak!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester