webForumDet fria alternativet

göra en count på en union

14 svar · 701 visningar · startad av swingman

swingmanMedlem sedan jan. 200686 inlägg
#1

hej...jag gillar i allmänt inte join satser...kan vara pga att jag inte förstår de riktigt.
Iaf så vill jag göra en count på en union som räknar resultat bara en gång.
mina 2 frågor som jag vill göra union på är följande:

SELECT COUNT(processdefinition_) AS nr
FROM jbpm_processdefinition d, jbpm_processinstance i
WHERE d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.start_) = year(CURRENT_TIMESTAMP)
SELECT COUNT(processdefinition_) AS nr
FROM jbpm_processdefinition d, jbpm_processinstance i
WHERE d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.end_) = year(CURRENT_TIMESTAMP);

Följande räknar inte bara en gång:

select
(SELECT COUNT(processdefinition_) AS nr
FROM jbpm_processdefinition d, jbpm_processinstance i
WHERE d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.start_) = year(CURRENT_TIMESTAMP))
+(SELECT COUNT(processdefinition_) AS nr
FROM jbpm_processdefinition d, jbpm_processinstance i
WHERE d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.end_) = year(CURRENT_TIMESTAMP));

Följande ger mig resultat i delad i 2 delar...alltså resultat för varje sats:

SELECT count(processdefinition_)
FROM jbpm_processdefinition d, jbpm_processinstance i
WHERE d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.start_) = year(CURRENT_TIMESTAMP)
UNION
SELECT count(processdefinition_)
FROM jbpm_processdefinition d, jbpm_processinstance i
WHERE d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.end_) = year(CURRENT_TIMESTAMP);

Kan nån hjälpa att skriva en sats som är lätt att förstå som ger rätt resultat!

nitro2k01Medlem sedan aug. 20039 342 inlägg
#2

Bara så att jag förstår dig rätt... Du vill beräkna hur många processinstanser som startas i år + hur många processinstanser som avslutas i år?
Med den metoden kommer instanser som båda påbörjas och avslutas i år räknas två gånger. Instanser som sträcker sig från ett tidigare år till ett år senare än 2009 kommer inte räknas alls. Det är kanske så du vill ha det, men skulle du kunna förklara med ord vad du vill ska räknas ut? :)

swingmanMedlem sedan jan. 200686 inlägg
#3

jo exakt...jag vill ha det så

jag vill bara kunna räkna ut instanser som påbörjas och avslutas i år. Men om samma instans påbörjas och avslutas i år ska den bara räknas en gång.

nitro2k01Medlem sedan aug. 20039 342 inlägg
#4
SELECT COUNT(processdefinition_) AS nr
FROM   jbpm_processdefinition d, jbpm_processinstance i
WHERE  d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and (
            year(i.end_) = year(CURRENT_TIMESTAMP) OR
            year(i.start_) = year(CURRENT_TIMESTAMP)
      )

...kanske?

swingmanMedlem sedan jan. 200686 inlägg
#5

precis så tänkte jag i början...inte för att jag vill verka bra men så dissade jag OR helt bara för att jag ville så gärna köra en union. Men tack så mycket för lösningen. Man behöver tänka rätt från början ibland.
Skulle du eller nån annan kunna berätta ändå om man skulle kunna lösa det här med en UNION? -Skulle bli intressant för mig att se.

nitro2k01Medlem sedan aug. 20039 342 inlägg
#6

Tricket är att använda UNION DISTINCT som sorterar bort dubletter i resultaten från underfrågorna. Om instanstabellen har en egen id-kolumn kan du byta ut i.* i båda underfrågorna till i.id_
Men se detta som ett rent studie-exempel, för det är itne så snyggt att använda join så här. :)

SELECT COUNT(*) AS nr FROM (
    SELECT i.*
    FROM   jbpm_processdefinition d, jbpm_processinstance i
    WHERE  d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.end_) = year(CURRENT_TIMESTAMP)
)
UNION DISTINCT
(
    SELECT i.*
    FROM   jbpm_processdefinition d, jbpm_processinstance i
    WHERE  d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.start_) = year(CURRENT_TIMESTAMP)
)
Peter SMedlem sedan dec. 20025 483 inlägg
#7

Värt att tillägga är att UNION och UNION DISTINCT är ekvivalenta. Det sistnämnda är även specifikt för MySQL :)

nitro2k01Medlem sedan aug. 20039 342 inlägg
#8

Peter S skrev:

Värt att tillägga är att UNION och UNION DISTINCT är ekvivalenta. Det sistnämnda är även specifikt för MySQL :)

Ah, det visste jag inte. Jag har sett till att alltid ange distinct eller all explicit så jag har itne brytt mig. Sen kanske man bör peka ut det självklara, att COUNT måste räknas ut efter UNION. (Alltså anges utanför parenteserna.)

swingmanMedlem sedan jan. 200686 inlägg
#9

fick ett error med din senaste lösning nitro2kO1, 21:32

när jag kör din fråga i MySql Browser får jag följande error:
Every derived table must have its own alias
:) :) :)

nitro2k01Medlem sedan aug. 20039 342 inlägg
#10
SELECT COUNT(*) AS nr FROM (
    SELECT i.*
    FROM   jbpm_processdefinition d, jbpm_processinstance i
    WHERE  d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.end_) = year(CURRENT_TIMESTAMP)
) i1
UNION DISTINCT
(
    SELECT i.*
    FROM   jbpm_processdefinition d, jbpm_processinstance i
    WHERE  d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.start_) = year(CURRENT_TIMESTAMP)
) i2

Gölmde lägga till alias för underfrågorna, i1 och i2 ovan.

swingmanMedlem sedan jan. 200686 inlägg
#11

fortf.fel...

jag vill inte störa dig. du har ju redan hjälpt mig med en fungerande lösning men det kan vara värt att säga ändå att det blir fortf. fel med den senaste koden. Felmedd: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 'i2' at line 11

nitro2k01Medlem sedan aug. 20039 342 inlägg
#12
SELECT COUNT(*) AS nr FROM (
    SELECT i.*
    FROM   jbpm_processdefinition d, jbpm_processinstance i
    WHERE  d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.end_) = year(CURRENT_TIMESTAMP)
UNION DISTINCT
    SELECT i.*
    FROM   jbpm_processdefinition d, jbpm_processinstance i
    WHERE  d.id_ = i.processdefinition_ and d.name_='ITSM - Change Management' and year(i.start_) = year(CURRENT_TIMESTAMP)
) i2

Så här då?

LarsGMedlem sedan dec. 200012 464 inlägg
#13
select count(distinct i.processdefinition_)
  from jbpm_processdefinition d 
  join jbpm_processinstance i
    on d.id_ = i.processdefinition_ 
  and d.name_='ITSM - Change Management' 
  and extract(year from current_date) in 
       (extract(year from i.end_),extract(year from i.start_))

Union distinct är inte specifkt för mysql. Det har funnits i SQL-standarden sedan 10 år tillbaka.

nitro2k01Medlem sedan aug. 20039 342 inlägg
#14

LarsG: Mitt allra första svar löste problemet, enda anledningen till att jag fortsatee posta är att swingman tydligen ville ha en lösning som använde union. Varför vet inte jag.
Men om när du har postat din kod låt mig ställa ett par frågor:
blir väl fel? Swingman vill veta antalet instanser, men count(distinct i.processdefinition_) ger väl tillbaka antalet prcoessdefinitioner som används då i.processdefinition_ pekar mot d's id-kolumn?
Varför extract istället för year?
Finns det några fördelar i detta fall att använda in istället för or inom parentes? (Förutom att koden blir snyggare ;) )

Peter SMedlem sedan dec. 20025 483 inlägg
#15

LarsG skrev:

Union distinct är inte specifkt för mysql. Det har funnits i SQL-standarden sedan 10 år tillbaka.

Hmpf :) Åtminstone Oracle, MSSQL och Postgresql stödjer det inte.

127 ms totalt · 3 externa anrop · v20260731065814-full.fb544a5a
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
124 ms — hämta tråd, inlägg och bilagor (db)