[mysql] Totale omzet per klant berekenen via een join

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • knarfyboy
  • Registratie: November 2001
  • Laatst online: 16-09 14:14
Heb een probleem met een query en ik kom er zo 123 niet uit. Ik heb 3 tabellen:

customers
Afbeeldingslocatie: https://tweakers.net/i/b-W9LfDVn409BPLj4m0h4jjl7C0=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/see5Vy8hKn15T39ef8lNiIev.png?f=user_large

products
Afbeeldingslocatie: https://tweakers.net/i/KnAa23cBxcc8mUoRAzUXuaqM6hY=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/XfhyfXzOaxDfoyUf6RcUDczo.png?f=user_large

sales
Afbeeldingslocatie: https://tweakers.net/i/8A6pyOkbEEEuBtROtu_2YTlN4_A=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/eIHRaMQh7PIW9rwPN3ZMujqy.png?f=user_large

Ik wil per emailadres uit customers het totaal aantal producten berekenen (een count van het aantal rijen in sales), en de totale omzet (aantal rijen in sales * price in products).

Nu heb ik bijna wat ik wil:
Afbeeldingslocatie: https://tweakers.net/i/CAkVyzWEtiLb16qcbiCpoYxbtWg=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/X51AUgfUSgv4fIqMyyfmyl9Z.png?f=user_large

Het enige probleem is dat ik ze niet gegroepeerd krijg per email adres. Ik wil dat de klant michael@email.com een omzet van 260000 genereerd, in plaats van 2 losse rijen.

Mijn query is als volgt:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
select
    c.email,
    total_products,
    revenue
from
    customers c
left join
    (select 
        product_id,
        email,
        count(product_id) as total_products,
        products.price * count(sales.product_id) as revenue
    from 
        sales,
        products
    where
        products.id = sales.product_id
    group by 
            sales.product_id,
            email
    ) s on s.email = c.email
left join
    (
    select
        products.id as product_id, 
        products.name as product_name
    from 
        products
    group by 
        products.id
    ) p on p.product_id = s.product_id


Als ik een group by c.email doe dan pakt hij alleen 1 rij die hij vindt van bij klant maar dit is niet wat ik wil (ik wil het totaal van alle rijen in sales):
Afbeeldingslocatie: https://tweakers.net/i/qgwdSeOMEHX1PIV4dC1J-TjoZ0Q=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/m51tHZyt2Y5JYomsOtPONjbO.png?f=user_large

Hoe kan ik dit voor elkaar krijgen?

Alle reacties


Acties:
  • +2 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Aangezien sales geen aantal heeft is het vrij eenvoudig ( Met aantal zou het overigens maar een kleine change zijn, want binnen de SUM/COUNT kun je ook gewoon een expressie gebruiken )
SQL:
1
2
3
4
5
SELECT s.email, COUNT(*) AS total_products, SUM(p.price) AS revenue
FROM sales s
INNER JOIN products p
    ON s.product_id = p.id
GROUP BY s.email

De query die jij toont is echt overmatig complex met joins op sub-query's e.d.

Dit is waarschijnlijk een testje, maar het data model lijkt mij niet erg solide. Voor verkopen wil je niet afhankelijk zijn van de prijs in de product tabel, maar die overeengekomen prijs wil je opnemen in de orderline ( jouw sales ) tabel. Immers wil je niet dat als later de prijs veranderd, dat nog impact heeft op je historische verkopen.

Tevens zou ik niet het e-mail adres gebruiken als primary-key voor je customers en foreign key in sales. Ik zou altijd een syntetische sleutel gebruiken zoals je ook in products doet. Dat geeft je de mogelijkheid om het mail-adres later nog te wijzigen, en grote kans dat het nog minder ruimte gebruikt, en sneller is.

[ Voor 33% gewijzigd door Woy op 09-03-2021 09:00 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • knarfyboy
  • Registratie: November 2001
  • Laatst online: 16-09 14:14
Je hebt gelijk, de data is op niet op een optimale manier gestructureerd en ik zou het nooit zo op deze manier indelen (dit is even een versimpeld voorbeeld van de echte data).

Alle nieuwe data komt nog steeds op deze manier binnen in deze webshop, hier kan ik helaas niets aan veranderen.