Avatar billede mosquito Nybegynder
21. marts 2006 - 18:50 Der er 18 kommentarer og
1 løsning

hvis id findes i første selection, skal union ikke foretages

Jeg arbejder på en sp, hvor jeg har brug for at liste seneste anvendte produkter.

Hvis produktid 1 ikke er anvendt, skal den tilføjes til listen, ellers skal den udelades.

Her er min nuværende sp, men får listet produkt 1 to gange, hvis den findes i første select.

@EmpID nvarchar(50)
   
AS

    SELECT DISTINCT TOP(10) prID, prName, MAX(hrID)
   
    FROM hrProducts
   
    JOIN RegHours ON hrProductID=prID
    JOIN Registrations ON regID=hrRegID
   
    WHERE regEmpID=@EmpID
   
    GROUP BY prName, prID
   
    UNION ALL
   
    SELECT prID, 'No product',null
   
    FROM hrProducts
   
    WHERE prID='1'
   
    ORDER BY MAX(hrID) DESC
   
RETURN


Hvordan undgår jeg at produkt 1 kan forekomme 2 gang i ovenstående sp?
Avatar billede kjulius Novice
21. marts 2006 - 20:54 #1
Du bruger UNION i stedet for UNION ALL
så fjerner den dubletter.
Avatar billede kjulius Novice
21. marts 2006 - 21:00 #2
Glem den kommentar :-(
Avatar billede kjulius Novice
21. marts 2006 - 22:27 #3
Måske sådan her?

SELECT * FROM (
SELECT DISTINCT TOP(10) prID, prName, MAX(hrID)
 
    FROM hrProducts
 
    JOIN RegHours ON hrProductID=prID
    JOIN Registrations ON regID=hrRegID
 
    WHERE regEmpID=@EmpID
 
    GROUP BY prName, prID
) AS X
UNION ALL
SELECT prID, 'No product',null
 
FROM hrProducts
 
WHERE prID='1' AND NOT EXISTS (
  SELECT * FROM X WHERE prID = hrProducts.prID)

Jeg har dog ingen anelse om det vil virke, men umiddelbart tiltaler den mig :-)
Du kan jo prøve...
Avatar billede mosquito Nybegynder
22. marts 2006 - 08:34 #4
Lovende, men den 'glemmer' at tilføje prID='1' hvis ikke den findes i X.d
Avatar billede mosquito Nybegynder
22. marts 2006 - 08:48 #5
Jeg havde også tænkt på om jeg kunne tilføje den i første selection ex. WHERE regEmpID=@EmpID OR prID='1', men den duer heller ikke.

til orientering, de tre tabeller det drejer sig om, som hænger sammen således:

Registrations
- regID
- regEmpID


RegHours
- hrID
- hrRegID
- hrProductID


hrProducts
-prID
-prName
Avatar billede ldanielsen Nybegynder
22. marts 2006 - 09:55 #6
Har du prøvet at bruge UNION uden ALL som kjulius foreslog? Det lyder da som løsningen ...
Avatar billede mosquito Nybegynder
22. marts 2006 - 10:00 #7
ja, det giver samme resultat ;-)
Avatar billede kjulius Novice
22. marts 2006 - 18:42 #8
---> Idanielsen:
Grunden til at jeg så hurtigt droppede idéen med bare UNION var, at jeg jo kunne se at hvis prID=1 var med i det første datasæt, ville bl.a. teksten jo nok ikke være 'No product' og ville derfor heller ikke blive fjernet af den "indbyggede" DISTINCT i UNION. Produktid ville derfor blive listet to gange alligevel (med to forskellige tekster)


---> mosquito: Min SQL giver altså ingen deciderede fejlmeldinger?

Hvad med:

SELECT * FROM (
SELECT TOP(10) prID, prName, MAX(hrID) AS Top_hrID
 
    FROM hrProducts
 
    JOIN RegHours ON hrProductID=prID
    JOIN Registrations ON regID=hrRegID
 
    WHERE regEmpID=@EmpID
 
    GROUP BY prName, prID
    ORDER BY MAX(hrID) DESC
) AS Top10

UNION ALL

SELECT prID, 'No product',null
 
FROM hrProducts
 
WHERE prID='1' AND NOT EXISTS (
  SELECT * FROM Top10 WHERE prID = hrProducts.prID)

ORDER BY Top_hrID DESC
Avatar billede kjulius Novice
22. marts 2006 - 19:26 #9
Jeg har nu genlæst dit oprindelige spørgsmål, og er kommet lidt i tvivl om, hvad formålet egentlig er. Hvis det bare er at liste de produkter der senest er foretaget registreringer til, dog altid incl. produkt 1, så burde denne her jo næsten kunne gøre det:

@EmpID nvarchar(50)
   
AS

    SELECT prID, CASE WHEN hrID IS NULL THEN 'No product' ELSE prName END AS prName, MAX(hrID)
   
    FROM hrProducts
   
    LEFT JOIN RegHours ON hrProductID=prID
    JOIN Registrations ON regID=hrRegID
   
    WHERE regEmpID=@EmpID
      AND (regID IS NOT NULL or prID = '1')
   
    GROUP BY prID, CASE WHEN hrID IS NULL THEN 'No product' ELSE prName END
    ORDER BY MAX(hrID) DESC
   
RETURN


Jeg går ud fra, at din TOP 10 instruktion kun har relevans her under testfasen (for at undgå for mange data på skærmen)?
Jeg har derfor fjernet denne instruktion. Ellers er der et problem med at sikre, at PrID 1 altid kommer med blandt de udvalgte.
Det kan dog sikkert også ordnes....
Avatar billede kjulius Novice
22. marts 2006 - 19:32 #10
Hvorfor har du i det hele taget tabellen Registrations med, hvis du ikke bruger felter herfra? Med mindre du har "fritstrejfende" entries i RegHours uden tilsvarende entries i Registrations som du ikke ønsker medtaget, er det vel ikke nødvendigt?
Avatar billede mosquito Nybegynder
22. marts 2006 - 19:44 #11
---> kjulius:

Ved at ændre Top10 til x, returnerer den nøjagtig samme resultat som dit første forslag. Er første selection tom eller uden prID='1', tilføjes prID'1' IKKE til det endelige dataset.
Avatar billede mosquito Nybegynder
22. marts 2006 - 19:45 #12
Registrations indeholder empID, som jeg selecter på
Avatar billede mosquito Nybegynder
22. marts 2006 - 19:47 #13
Top10 skal bruges, da datasettet er til en dropdown.
Avatar billede mosquito Nybegynder
22. marts 2006 - 19:49 #14
forslag fra kl. 19:26 giver heller ikke prID'1' uden den er i første selection.
Avatar billede kjulius Novice
23. marts 2006 - 00:52 #15
ref 19:44 - Nu var der jo lidt mere end en omdøbning til Top10 fra X i det ændrede forslag, bla.a. er der tilføjet et ORDER BY i den indre forespørgsel (for at få de rigtige 10 rows), men du har da ret. Der er ikke store ændringer i forhold til det oprindelige forslag.

Jeg har en enkelt ændring, som i hvert fald i min Access gør en forskel:

SELECT * FROM (
SELECT TOP(10) prID, prName, MAX(hrID) AS Top_hrID

    FROM hrProducts

    JOIN RegHours ON hrProductID=prID
    JOIN Registrations ON regID=hrRegID

    WHERE regEmpID=@EmpID

    GROUP BY prName, prID
    ORDER BY MAX(hrID) DESC
) AS Top10

UNION ALL

SELECT hrProducts.prID, 'No product' AS prName, Null AS Sidstereg
FROM hrProducts
WHERE ((hrProducts.prID=1)
  AND (hrProducts.prID NOT IN (SELECT Top10.prID FROM Top10))
ORDER BY Top_hrID DESC

ref 19:45 - Sorry, det havde jeg overset :-(

ref 19:47 - Okay...

ref 19:49 - så måske:

@EmpID nvarchar(50)
 
AS

    SELECT prID, CASE WHEN hrID IS NULL THEN 'No product' ELSE prName END AS prName, MAX(hrID)
 
    FROM hrProducts
 
    LEFT JOIN RegHours ON hrProductID=prID
    JOIN Registrations ON regID=hrRegID
 
    WHERE regEmpID=@EmpID
      OR (regEmpID IS NULL AND prID = '1')
 
    GROUP BY prID, CASE WHEN hrID IS NULL THEN 'No product' ELSE prName END
    ORDER BY MAX(hrID) DESC
 
RETURN
Avatar billede kjulius Novice
23. marts 2006 - 00:57 #16
Begge joins bør vel være LEFT JOIN ... tror jeg...
Avatar billede mosquito Nybegynder
23. marts 2006 - 08:21 #17
ref 19:44 Troede Top10 skulle opfattes som et alias for første selection, men fik en fejl (Invalid object name 'Top10'), men ændrede jeg 'Top10' til 'x', var der ingen problemer.

Derudover var jeg en tur i tabellen og så at prID'1' ikke var navneløs, jeg havde forvekslet det med orderID'1', hvor jeg så til gengæld står med problemet, men nu er jeg sikker på jeg har informationer nok til at klare den sag også :-)

Din seneste løsning fungerer fint, og returnerer det den skal, når jeg fjerner 'regEmpID IS NULL AND'.

Mange tak for hjælpen. Smid et svar, dine point er velfortjent ;-)
Avatar billede kjulius Novice
23. marts 2006 - 08:54 #18
Glad for at være til hjælp...
Avatar billede mosquito Nybegynder
23. marts 2006 - 09:00 #19
til dem der måtte have glæde af det andet problem, hvor 'orderNbr' is null. Her blev jeg nødt til at gøre brug af endnu en LEFT JOIN for at få det til at virke. Endnu et problem blev løst ;-)

SELECT TOP(10) orderID, CASE WHEN orderID='1' THEN 'No product' ELSE orderNbr END AS orderNbr, MAX(hrID)
 
    FROM Orders
 
    LEFT JOIN RegHours ON hrOrderNbr=orderNbr
    LEFT JOIN Registrations ON regID=hrRegID
   
    WHERE regEmpID=@EmpID OR orderID = '1'
 
    GROUP BY orderID, orderNbr
    ORDER BY MAX(hrID) DESC
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



IT-JOB