Avatar billede chrisrj Forsker
19. april 2019 - 21:44 Der er 33 kommentarer og
1 løsning

Kunsten af få data ud i korrekt rækkefølge

Hejsa


Jeg er ved at lave en dynamisk menu med undermenuer.

Jeg vil derfor gerne hive menupunkterne ud i korrekt rækkefølge.

Lige nu har jeg En SortOrder og en Parent. Parent står til 0 ved alle "hovedmenupunkter", ved undermenupunkter står Parenti til et hovedmenupunkts MenuID.
Eks.
Navn, MenuID, SortOrder, Parent
Log ud, 0, 0, 0
Kundeoversigt, 1, 1, 0
Opret Kunde, 2, 0, 1
Maskinoversigt, 3, 2, 0
Opret Maskine, 4, 0, 3

De to Opret rækker er undermenuer.

Lige nu ser min SQL således ud:
SELECT DISTINCT a.MenuID, a.MenuName, a.MenuLink, a.MenuVisible, a.MID, a.Parent, b.FieldName, b.DefaultText, b.'.$LangNameColName.'
FROM '.MenuTable.' AS a, '.LanguageTextsTable.' AS b
WHERE a.MenuName = b.DefaultText AND (b.FieldName LIKE "Menu%")
ORDER BY a.SortOrder, a.Parent

Men problemet er, at alle undermenupunkter kommer ud sammen (under første hovedmenupunkt med undermenuer)
Avatar billede arne_v Ekspert
19. april 2019 - 23:26 #1
ORDER BY a.Parent, a.SortOrder

?
Avatar billede chrisrj Forsker
19. april 2019 - 23:34 #2
Heh, desværre ikke. :D

Det rykker dem bare ned til sidste hovedmenu.
Avatar billede arne_v Ekspert
19. april 2019 - 23:49 #3
SELECT
...
menutable a1 JOIN menutable a2 on a1.menuid = a2.parent
...
ORDER BY a1.SortOrder, a2.SortOrder

?
Avatar billede chrisrj Forsker
19. april 2019 - 23:52 #4
Øhm...ikke for at være besværlig...men hvor skal
menutable a1 JOIN menutable a2 on a1.menuid = a2.parent
ind?? :D
Avatar billede arne_v Ekspert
20. april 2019 - 00:02 #5
erstatte

MenuTable a
Avatar billede chrisrj Forsker
20. april 2019 - 00:11 #6
Ah, ok.

Hmm, hvis jeg gør således:
'.MenuTable.' a1 JOIN '.MenuTable.' a2 on a1.menuid = a2.parent AS a

Kommer denne fejl:
Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS a, PoC_LanguageTexts AS b WHERE a.MenuName = b.DefaultText AND ' at line 2


Hvis jeg fjerner "as a", skal jeg rette a til a1/a2 alle steder...

Huh? Nu kommer der kun 4 ud af 12 menupunkter ud??
Avatar billede arne_v Ekspert
20. april 2019 - 00:24 #7
AS a skal vaek.

Hvis der mangle rnogen saa proev LEFT JOIN i.s.f. JOIN.
Avatar billede chrisrj Forsker
20. april 2019 - 00:29 #8
Ok.

Så er vi tilbage til det oprindelige resultat. :-/

SELECT DISTINCT a1.MenuID, a1.MenuName, a1.MenuLink, a1.MenuVisible, a1.MID, a1.Parent, b.FieldName, b.DefaultText, b.'.$LangNameColName.'
FROM '.MenuTable.' a1 LEFT JOIN '.MenuTable.' a2 on a1.menuid = a2.parent, '.LanguageTextsTable.' AS b
WHERE a1.MenuName = b.DefaultText AND (b.FieldName LIKE "Menu%")
ORDER BY a1.SortOrder, a2.SortOrder
Avatar billede arne_v Ekspert
20. april 2019 - 00:48 #9
Proev og udskrive baade a1.MenuName og a2.MenuName.
Avatar billede chrisrj Forsker
20. april 2019 - 00:54 #10
Hmm...Jah, hvis jeg gør det i databasen (i koden vil det være møj besværligt), så kommer a2 navnene godt nok sammen med de rette hovedmenupunkter, men ikke som selvstændige rækker som de skal være.
Avatar billede arne_v Ekspert
20. april 2019 - 03:13 #11
Ja. Men en SELECT udtraekker nu engang en data rektangel.

Applikationen kan teste paa om a1.MenuName er det samme som raekken foer.
Avatar billede chrisrj Forsker
20. april 2019 - 12:29 #12
Tja, hvis jeg gør således:
SELECT DISTINCT a1.MenuID, a1.MenuName, a2.MenuName as MenuNameC, a1.MenuLink, a2.MenuLink as MenuLinkC, a1.MenuVisible, a1.MID, a1.SortOrder, b.FieldName, b.DefaultText, b.EnglishText
FROM PoC_Menu a1 LEFT JOIN PoC_Menu a2 on a1.menuid = a2.parent, PoC_LanguageTexts AS b
WHERE a1.MenuName = b.DefaultText AND (b.FieldName LIKE "Menu%") AND a1.Parent = 0
ORDER BY a1.SortOrder, a2.SortOrder

Får jeg i hvert fald de nødvendige data ud. Ikke så kønt som jeg havde håbet på, men det virker. :)
Avatar billede chrisrj Forsker
20. april 2019 - 18:05 #13
Arg, ser lige at jeg mangler jo b.FieldName, b.DefaultText, b.EnglishText på a2 (undermenupunkterne). :-/

What to do??
Avatar billede arne_v Ekspert
21. april 2019 - 00:11 #14
FROM PoC_Menu a1 LEFT JOIN PoC_Menu a2 on a1.menuid = a2.parent, PoC_LanguageTexts AS b WHERE a1.MenuName = b.DefaultText

->

FROM PoC_Menu a1 LEFT JOIN PoC_Menu a2 on a1.menuid = a2.parent,
JOIN PoC_LanguageTexts AS b1 ON a1.MenuName = b1.DefaultText
JOIN PoC_LanguageTexts AS b2 ON a2.MenuName = b2.DefaultText

saa du har baade en b1 og en b2 som svarer til a1 og a2.
Avatar billede chrisrj Forsker
21. april 2019 - 00:47 #15
Hmm.. det giver syntax fejl.
'JOIN PoC_LanguageTexts AS b1 ON a1.MenuName = b1.DefaultText JOIN ' at line 3

Jeg prøvede at sætte et komme ind, men det hjalp ikke.
Avatar billede chrisrj Forsker
21. april 2019 - 01:01 #16
Ah, ved at fjerne kommaet efter  a2.parent, er der ikke mere syntax fejl. :)

Til gengæld er der så problemer i WHERE. :D
WHERE a1.MenuName = b.DefaultText AND (b.FieldName LIKE "Menu%") AND a1.Parent = 0

Retter jeg b til b1 kommer der kun dem med undermenuer, retter jeg til b2, kommer der ingenting.
Avatar billede arne_v Ekspert
21. april 2019 - 01:01 #17
der skal ikke vaere komma - heller ikke der hvor jeg har det i #14 !
Avatar billede chrisrj Forsker
21. april 2019 - 01:04 #18
Vi fik vist lige krydset hinanden der. :)
Avatar billede arne_v Ekspert
21. april 2019 - 01:15 #19
a1.MenuName = b.DefaultText

skal helt udgaa da den nu er i JOIN ON
Avatar billede arne_v Ekspert
21. april 2019 - 01:16 #20
b.FieldName LIKE "Menu%"

skal enten vaere b1 eller vaere b2 eller teste paa begge med AND imellem
Avatar billede chrisrj Forsker
21. april 2019 - 01:22 #21
WHERE a1.MenuName = b1.DefaultText AND (b1.FieldName LIKE "Menu%" AND b2.FieldName LIKE "Menu%") AND a1.Parent = 0

Giver ikke nogen ændring i resultatet.

WHERE a1.MenuName = b1.DefaultText AND (b2.FieldName LIKE "Menu%") AND a1.Parent = 0

Giver underligt nok en doublet på een af menuerne. Men ellers ikke nogen ændring.
Avatar billede arne_v Ekspert
21. april 2019 - 03:06 #22
Jeg tror at det er tid til at tage et skrift tilbage.

1) Proev:

SELECT a1.*,b1.*,a2.*,b2.*
FROM PoC_Menu a1 LEFT JOIN PoC_Menu a2 on a1.menuid = a2.parent,
JOIN PoC_LanguageTexts AS b1 ON a1.MenuName = b1.DefaultText
JOIN PoC_LanguageTexts AS b2 ON a2.MenuName = b2.DefaultText

og se hvad du faar.

2) Put WHERE betingelser paa indtil du faar de rigtige raekker

3) Hent kun de kolonner som du skal bruge
Avatar billede chrisrj Forsker
21. april 2019 - 10:47 #23
Sjovt, jeg sad selv og tænkte at det så ret komplekst ud i forhold til hvad det gør... :)

1) (*husker lige at fjerne kommaet* ;) )
Uden WHERE: 4 R, heraf en doublet (alle kun undermenupunkter)

2) Med:
WHERE a1.MenuName = b1.DefaultText AND (b2.FieldName LIKE "Menu%") AND a1.Parent = 0
Samme resultat

At fjerne dele af WHERE ændre heller ikke noget.
Jeg ser ikke lige mulighed for at få FLERE rækker ud via dette?
Avatar billede chrisrj Forsker
21. april 2019 - 12:37 #24
Måske et billede af de faktiske rådata kunne hjælpe?

https://drive.google.com/open?id=113s52XhMLTsIow3aTiMsOsq5PqURLoEf
Avatar billede arne_v Ekspert
22. april 2019 - 04:44 #25
Kunne du poste CREATE TABLE og INSERT statements?

(lidt nemmere)
Avatar billede chrisrj Forsker
22. april 2019 - 09:56 #26
Here ya go:

--
-- Struktur-dump for tabellen `PoC_Menu`
--

CREATE TABLE IF NOT EXISTS `PoC_Menu` (
  `MenuID` int(11) NOT NULL AUTO_INCREMENT,
  `MenuName` varchar(25) NOT NULL,
  `MenuLink` varchar(200) NOT NULL,
  `MenuVisible` tinyint(1) NOT NULL DEFAULT '1',
  `SortOrder` int(2) NOT NULL,
  `Parent` int(11) NOT NULL DEFAULT '0',
  `MID` int(11) NOT NULL COMMENT 'ModuleID',
  PRIMARY KEY (`MenuID`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=13 ;

--
-- Data dump for tabellen `PoC_Menu`
--

INSERT INTO `PoC_Menu` (`MenuID`, `MenuName`, `MenuLink`, `MenuVisible`, `SortOrder`, `Parent`, `MID`) VALUES
(1, 'Menu entries', 'menulist.php', 1, 0, 0, 1),
(2, 'Create menu entry', 'menucreate.php', 1, 0, 1, 1),
(4, 'Deploy', 'deploy.php', 1, 1, 0, 1),
(5, 'Languages', 'languagelist.php', 1, 2, 0, 1),
(6, 'Language modules', 'languagemodulelist.php', 1, 0, 5, 1),
(7, 'Event Log', 'loglist.php', 1, 3, 0, 1),
(8, 'Supporters', 'adminlist.php', 1, 4, 0, 1),
(9, 'Customers', 'customerlist.php', 1, 5, 0, 1),
(10, 'Create customer', 'customercreate.php', 1, 0, 9, 1),
(11, 'Statistics', 'stats.php', 1, 6, 0, 1),
(12, 'Change password', 'changepw.php', 1, 7, 0, 1);
Avatar billede arne_v Ekspert
23. april 2019 - 05:24 #27
Hvad siger du til den her:

mysql> SELECT menuname AS a1name,sortorder AS a1order,'----' AS a2name,-1 AS a2o
rder
    -> FROM poc_menu
    -> WHERE parent = 0
    -> UNION
    -> SELECT a1.menuname AS a1name,a1.sortorder AS a1order,a2.menuname AS a2name,a2.sortorder AS a2order
    -> FROM poc_menu a1 JOIN poc_menu a2 ON a1.menuid = a2.parent
    -> ORDER BY a1order, a2order;
+-----------------+---------+-------------------+---------+
| a1name          | a1order | a2name            | a2order |
+-----------------+---------+-------------------+---------+
| Menu entries    |      0 | ----              |      -1 |
| Menu entries    |      0 | Create menu entry |      0 |
| Deploy          |      1 | ----              |      -1 |
| Languages      |      2 | ----              |      -1 |
| Languages      |      2 | Language modules  |      0 |
| Event Log      |      3 | ----              |      -1 |
| Supporters      |      4 | ----              |      -1 |
| Customers      |      5 | ----              |      -1 |
| Customers      |      5 | Create customer  |      0 |
| Statistics      |      6 | ----              |      -1 |
| Change password |      7 | ----              |      -1 |
+-----------------+---------+-------------------+---------+
11 rows in set (0.00 sec)
Avatar billede chrisrj Forsker
23. april 2019 - 10:07 #28
Hmm...jah, jeg får i hvert fald samme output når jeg kører den.

Men jeg er ikke gode venner med dubletterne. :-/

Men hvis jeg kigger på den næste rækkes a2name, og den så er forskellig fra --- så er det undermenuen...

Hmm...tjoh, så mangler jeg bare resten af felterne! :D
Avatar billede arne_v Ekspert
23. april 2019 - 17:23 #29
Du skal have flere a1 og a2 felter.

Og du skal nok have joinet b1 og b2 ind igen.
Avatar billede arne_v Ekspert
23. april 2019 - 17:25 #30
Det grundliggende problem er at data strukturen ikke passer godt ind i den relationelle model.
Avatar billede chrisrj Forsker
23. april 2019 - 20:58 #31
Hmm...

Laver jeg dette:
SELECT menuname AS a2name, MenuLink, sortorder AS a1order,-1 AS a2order
FROM PoC_Menu
WHERE parent = 0
UNION
SELECT a2.menuname AS a2name, a2.MenuLink, a1.sortorder AS a1order,a2.sortorder AS a2order
FROM PoC_Menu a1 JOIN PoC_Menu a2 ON a1.menuid = a2.parent
ORDER BY a1order, a2order;


Ser det foreløbige faktisk ret ok ud...prøver lige og se hvad jeg kan gøre med b...
Avatar billede chrisrj Forsker
23. april 2019 - 21:07 #32
Nå, det kan jeg åbenbart ikke gennemskue hvordan det gøre.

Dette:
SELECT menuname AS a2name, MenuLink, sortorder AS a1order,-1 AS a2order, b1.DefaultText, b2.DefaultText
FROM PoC_Menu, PoC_LanguageTexts
WHERE parent = 0
UNION
SELECT a2.menuname AS a2name, a2.MenuLink, a1.sortorder AS a1order,a2.sortorder AS a2order, b1.DefaultText, b2.DefaultText
FROM PoC_Menu a1 JOIN PoC_Menu a2 ON a1.menuid = a2.parent
JOIN PoC_LanguageTexts AS b1 ON a1.MenuName = b1.DefaultText
JOIN PoC_LanguageTexts AS b2 ON a2.MenuName = b2.DefaultText
ORDER BY a1order, a2order;

Giver:
Unknown column 'b1.DefaultText' in 'field list'
Avatar billede arne_v Ekspert
23. april 2019 - 21:14 #33
Du skal ogsaa joine PoC_LanguageTexts ind i foerste del.

Noget a la:

SELECT menuname AS a2name, MenuLink, sortorder AS a1order,-1 AS a2order, DefaultText, '-'
FROM PoC_Menu JOIN PoC_LanguageTexts ON PoC_Menu.MenuName = PoC_LanguageTexts.DefaultText
WHERE parent = 0
UNION
...
Avatar billede chrisrj Forsker
23. april 2019 - 21:28 #34
Awesome! Nu tror jeg sgu den er der. :) :)

SELECT MenuID, MenuLink, MenuVisible, MID, sortorder AS SortOrder ,-1 AS ChildOrder, FieldName, DefaultText, EnglishText
FROM PoC_Menu JOIN PoC_LanguageTexts ON PoC_Menu.MenuName = PoC_LanguageTexts.DefaultText
WHERE parent = 0 AND FieldName LIKE "Menu%"
UNION
SELECT a2.MenuID, a2.MenuLink, a2.MenuVisible, a2.MID, a1.sortorder AS SortOrder ,a2.sortorder AS ChildOrder, b2.FieldName, b2.DefaultText, b2.EnglishText
FROM PoC_Menu a1 JOIN PoC_Menu a2 ON a1.menuid = a2.parent
JOIN PoC_LanguageTexts AS b1 ON a1.MenuName = b1.DefaultText
JOIN PoC_LanguageTexts AS b2 ON a2.MenuName = b2.DefaultText
ORDER BY SortOrder, ChildOrder;
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

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