84

I have two tables: Toys and Games.

+--------------------+------------------+
| Field              | Type             |
+--------------------+------------------+
| toy_id             | int(10) unsigned |
| little_kid_id      | int(10) unsigned |
+--------------------+------------------+

+--------------------+------------------+
| Field              | Type             |
+--------------------+------------------+
| game_id            | int(10) unsigned |
| little_kid1        | int(10) unsigned |
| little_kid2        | int(10) unsigned |
| little_kid3        | int(10) unsigned |
+--------------------+------------------+

A little kid can have multiple toys. A little kid can be participating in multiple games at once.

I want a query that will give me the total number of toys + games that a little_kid is involved with.

Basically, I want the sum of these two queries:

SELECT COUNT(*) FROM Toys WHERE little_kid_id = 900;
SELECT COUNT(*) from Games WHERE little_kid1 = 900 
                              OR little_kid2 = 900 
                              OR little_kid3 = 900;

Is it possible to get this in a single SQL query? Obviously, I can sum them programmatically, but that's less desirable.

(I realize that the contrived example makes the schema look ineffecient. Let's assume that we can't change the schema.)

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Runcible
  • 7,006
  • 12
  • 42
  • 62

8 Answers8

181

Wrap them up and use subqueries:

SELECT
(SELECT COUNT(*) FROM Toys WHERE little_kid_id = 900)+
(SELECT COUNT(*) from Games WHERE little_kid1 = 900 
                              OR little_kid2 = 900 
                              OR little_kid3 = 900)
AS SumCount

Voila!

Eric
  • 92,005
  • 12
  • 114
  • 115
  • how can we get it without sub-query – Greesh Kumar Nov 08 '16 at 11:18
  • 1
    This won't work in Oracle without the FROM keyword. Apparently MySQL allows it! – Sampath Mar 11 '21 at 11:22
  • 1
    Use following on Oracle: `SELECT (SELECT COUNT(*) FROM Toys WHERE little_kid_id = 900)+ (SELECT COUNT(*) from Games WHERE little_kid1 = 900 OR little_kid2 = 900 OR little_kid3 = 900) AS SumCount FROM DUAL`; – Sampath Apr 21 '21 at 05:57
12
SELECT
((SELECT COUNT(*) FROM Toys WHERE little_kid_id = 900)+
(SELECT COUNT(*) from Games WHERE little_kid1 = 900 
                              OR little_kid2 = 900 
                              OR little_kid3 = 900))
AS Sum FROM DUAL;

Selecting from the DUAL Table

adprocas
  • 1,863
  • 1
  • 14
  • 31
anish
  • 147
  • 1
  • 3
  • 2
    Provide description to your answer please. – MKR Feb 16 '18 at 13:19
  • Note: Selecting from the `dual` table is required for Oracle, but not MySQL. Therefore, for this specific question, [this answer](https://stackoverflow.com/a/826375/6340496) is more accurate. – S3DEV Sep 07 '20 at 08:46
  • 1
    Isn't this the same as the accepted answer? It's just wrapped in extra parentheses – Sebastián Palma Mar 19 '21 at 11:22
7
SELECT COUNT(1) FROM
(
    SELECT 1 FROM Toys WHERE little_kid_id = 900
    UNION
    SELECT 1 FROM Games WHERE little_kid1 = 900
                        OR little_kid2 = 900
                        OR little_kid3 = 900
)
Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
5

Depending on how much this query is likely to be run and how often the data changes you could periodically put data into an aggregated table like this:

CREATE TABLE aggregated (
    little_kid_id INT UNSIGNED,
    games_count INT UNSIGNED,
    toys_count INT UNSIGNED,
    PRIMARY KEY (little_kid_id)
);

Performance wise that would be s**t hot fast and avoids any nasty sub-queries.

James C
  • 14,047
  • 1
  • 34
  • 43
3

Try this one...

db: mysql

SELECT  SUM(dum.tab) AS total FROM (
SELECT COUNT(b.category_id) AS tab FROM tblcategory AS b WHERE b.category_id=1
UNION  ALL
SELECT COUNT(a.category_id) AS tab FROM tblcategory AS a WHERE a.category_id=2
) AS dum
Gunther Struyf
  • 11,158
  • 2
  • 34
  • 58
0
  SELECT  M.*,M.TOYSCOUNT+M.GAMECOUNT  
FROM (
    (SELECT COUNT(*) FROM Toys WHERE little_kid_id) AS TOYSCOUNT,
    (SELECT COUNT(*) from Games WHERE little_kid1 = 900 OR little_kid2 = 900 OR little_kid3 = 900) AS GAMECOUNT
    ) M
0
SELECT COUNT(1) FROM
(
    (SELECT 1 FROM Toys WHERE little_kid_id = 900
    UNION
    SELECT 1 FROM Games WHERE little_kid1 = 900
                        OR little_kid2 = 900
                        OR little_kid3 = 900) as temptable
)
PhantomReference
  • 718
  • 2
  • 14
  • 27
-1
select t1.tx,t2.px,t3.mx,t2.px + t3.mx  
        as total from(
SELECT COUNT (DISTINCT id) as tx
FROM Customer) as t1
cross join(
select COUNT (DISTINCT name) as px
FROM details 
) as t2
cross join(
select count (distinct device_id) as mx
from detailconfig 
) as t3
Pika Supports Ukraine
  • 3,612
  • 10
  • 26
  • 42
Arul
  • 1
  • 1