DMande
DMande

Reputation: 341

mysql return same rows union

In my database i have categories, offers and coupons. i would like to count offers and coupons that exist in each category. when i use union it returns the same category twice. i have the below query that returning same category rows with same name. i try to use union distinct but it does not work.

(SELECT 
        cat1.id AS cat1id, cat1.title AS title,
        count(offers.id) AS offercounter

    FROM cat1

    INNER JOIN offers 
    ON offers.category=cat1.title

    GROUP BY cat1.id
    order by cat1.order)
     UNION
    (SELECT 
        cat1.id AS cat1id, cat1.title AS title,
        count(coupons.id) AS couponscounter

    FROM cat1

    INNER JOIN coupons 
    ON coupons.category=cat1.title

    GROUP BY cat1.id
    order by cat1.order)

the result

cat1id  title         offercounter
 2       Food              5388
 23      Clothes           6000(this is offers)
 32      Technology         499
 40      Clothes            4(this is coupons)

i would like clothes to be (offercounter + couponscounter). example: clothes=6004 and not two different rows

the desired result would be :

cat1id  title         offercounter
 2       Food              5388
 23      Clothes           6004(offers+coupons)
 32      Technology         499

Upvotes: 1

Views: 96

Answers (4)

Kickstart
Kickstart

Reputation: 21513

Alternative avoiding unions or sub queries is to use a couple of LEFT OUTER JOINS, and count the distinct ids from each table:-

SELECT cat1.id AS cat1id, 
        cat1.title AS title,
        COUNT(DISTINCT offers.id) + COUNT(DISTINCT coupons.id) AS offercounter
FROM cat1
LEFT OUTER JOIN offers ON offers.category = cat1.title
LEFT OUTER JOIN coupons ON coupons.category = cat1.title
GROUP BY cat1.id AS cat1id, 
        cat1.title AS title

EDIT

A left outer join will return a row of nulls when there is no matching row.

For example if there was a row on cat1 with a matching row on offers but no matching row on coupons then the resulting row would consist of the row from cat1, the row from offers and the fields from coupons would be null.

This SQL will get every combination of matching rows. So if you had:-

cat1 fields     offers fields       coupons fields
id  title       id      category    id      category
1   fred        99      fred        77      fred
1   fred        99      fred        88      fred
1   fred        100     fred        77      fred
1   fred        100     fred        88      fred
2   burt        120     fred        NULL    NULL
2   burt        121     fred        NULL    NULL

Hence the count uses DISTINCT to only could each id within a category once. As COUNT(field name) only counts non null values, with this example data for the 2nd category the count from coupons will be 0.

Upvotes: 2

Fake Face
Fake Face

Reputation: 116

May be this can help.

SELECT cat1.id AS cat1id, cat1.title AS title ,((SELECT COUNT(offers.id) FROM offers WHERE offers.category=cat1.title)+(SELECT COUNT(coupons.id) FROM coupons WHERE coupons.category=cat1.title)) AS offercounter
FROM cat1

Upvotes: 0

Noman
Noman

Reputation: 4116

Why don't you simple sum up the offercounter and use group by with order by cat1id.

SELECT cat1id,title,sum(offercounter) as offercounter 
FROM offers GROUP BY title ORDER BY cat1id

View : SQL Fiddle

Output :

cat1id   title            offercounter
 2       Food             5388
 23      Clothes          6004
 32      Technology       499

Upvotes: 0

AdrianBR
AdrianBR

Reputation: 2588

Union returns distinct rows. Your returned rows are distinct indeed. What you need to do to get your desired result is aggregate after unioning.

select min(cat1id) as cat1id, title, sum(offercounter) as offercounter
 from 
(your_query) as subquery
group by title

replace your_query with your existing query

Upvotes: 2

Related Questions