Set column name for multiple select count (*) tables - mysql

How can I set a column name for the output from bellow query ?
select
(select count(*) from t_table1 id = 1)
+
(select count(*) from t_table2 id = 1)
+
(select count(*) from t_table3 id = 1)

Use as:
select ( (select count(*) from t_table1 where id = 1) +
(select count(*) from t_table2 where id = 1) +
(select count(*) from t_table3 where id = 1)
) as col
Notice that I put the entire expression in parentheses. This is not required, but it makes the code more readable. I also fixed the subqueries.
If you want to run this multiple times, then a correlated subquery makes it easier to manage the ids:
select ( (select count(*) from t_table1 t where t.id = x.id) +
(select count(*) from t_table2 t where t.id = x.id) +
(select count(*) from t_table3 t where t.id = x.id)
) as col
from (select 1 as id) x;
Then, to modify the query, you only need to change the value in one place.

use as Keyword
select (select count(*) from t_table1 id = 1)+
(select count(*) from t_table2 id = 1)+
(select count(*) from t_table3 id = 1) as result

select sum(count_tab) as col_name from(
(select count(*) as count_tab from t_table1 id = 1)
union all
(select count(*) from t_table2 id = 1)
union all
(select count(*) from t_table3 id = 1))

Related

MySQL: In a single query, how can I check if a specific group of associations exist?

I have a table like this:
groupID | username
------------------
1 | joe1
1 | bobby
2 | joe1
3 | joe1
3 | bobby
3 | sally
I want to check if there exists a group ID with only joe1 and bobby (in this case it would be true because groupID 1 has exactly joe1 and bobby).
Here is one way:
select exists (
select groupID
from tbl
group by groupID
having group_concat(username order by username) = 'bobby,joe1'
) as group_exists
You need to pass the usernames sorted.
Works when username doesn't contain a comma.
Another way:
select exists (
select groupID
from tbl
group by groupID
having sum(username in ('bobby','joe1')) = 2
and count(*) = 2
) as group_exists
But here you need to maintain the count of the input names (2 in this case).
And here is something fency for MariaDB supporting VALUES() in SELECT queries:
with input(username) as (
VALUES ('joe1'), ('bobby')
)
select exists (
select t.groupID
from input i
natural join tbl t
group by t.groupID
having count(*) = (select count(*) from input)
and count(*) = (select count(*) from tbl t1 where t1.groupID = t.groupID)
) as group_exists
For MySQL 8 you can use a UNION query as CTE:
with input(username) as (
select 'joe1' union select 'bobby'
)
select exists (
select t.groupID
from input i
natural join tbl t
group by t.groupID
having count(*) = (select count(*) from input)
and count(*) = (select count(*) from tbl t1 where t1.groupID = t.groupID)
) as group_exists
Or pass the usernames as JSON array and parse it with JSON_TABLE():
with input as (
select username
from json_table(
'["joe1","bobby"]',
'$[*]' columns (username varchar(100) path '$')
) j
)
select exists (
select t.groupID
from input i
natural join tbl t
group by t.groupID
having count(*) = (select count(*) from input)
and count(*) = (select count(*) from tbl t1 where t1.groupID = t.groupID)
) as group_exists
Or this one, which might be simpler but slower:
select exists (
select t.groupID
from (select '["joe1","bobby"]' as input) i
cross join tbl t
group by t.groupID, i.input
having count(*) = json_length(i.input)
and sum(json_contains(i.input, json_quote(t.username), '$')) = json_length(i.input)
) as group_exists

Sort the table in sequential conditions?

I have a users table with 5 columns, id, age, is_premium, is_male, is_customer where id is the primary key.
First statement I do is. This statement has the potential of returning 0 rows:
SELECT * FROM users
WHERE is_premium = 1 AND
is_name = 0 AND
is_customer = 0
Then ONLY from the rows I got from the above query, I want to find the person with the largest age.
SELECT * FROM <from the above query>
WHERE id = (SELECT MAX(ID) <from the above query>)
Question: How do make these 2 separate SQL statements into a single statement and what is the most efficient way of doing this?
why not directly:
SELECT *
FROM users
WHERE is_premium = 1
AND is_name = 0
AND is_customer = 0
ORDER BY age DESC, id ASC
LIMIT 1
for mysql version 8 and above you can also use common table expressions (CTE):
WITH D AS (
SELECT * FROM users
WHERE is_premium = 1
AND is_name = 0
AND is_customer = 0
)
SELECT *
FROM D
WHERE AGE = (SELECT MAX(AGE) FROM D)
ORDER BY ID
LIMIT 1
Assuming you have a primary key column called id, just move the query in a sub-query:
SELECT *
FROM users
WHERE id = (
SELECT id
FROM users
WHERE is_premium = 1 AND is_name = 0 AND is_customer = 0
ORDER BY age DESC
LIMIT 1
)
suppose you will have multiple users with same max() age
select * from users t1
inner join (
select max(age) maxage from users
where is_premium=1 and is_name=0 and is_customer=0) t2
on t2.maxage = t1.age
where is_premium=1 and is_name=0 and is_customer=0
or if you don't want to repeat your conditions.
select * from users t1
inner join(
select
(select max(t.age) from users t where t.id = t2.id) as maxage,
t2.id
from users t2
where is_premium=1 and is_name=0 and is_customer=0) t3 on t3.id = t1.id

How to select data that doesn't exist in other query

I'm trying to select from table data but i want the result not exist in this select.
(SELECT * FROM data WHERE category = 'A' ORDER BY RAND() LIMIT 4)
UNION ALL
(SELECT * FROM data WHERE category = 'B' ORDER BY RAND() LIMIT 4)`
So there are no row that been selected double.
Fiddle with sample data.
With NOT EXISTS:
SELECT * FROM table1 t1
WHERE NOT EXISTS (
SELECT 1 FROM (
(SELECT * FROM table1 WHERE category = 'A' ORDER BY RAND() LIMIT 4)
UNION ALL
(SELECT * FROM table1 WHERE category = 'B' ORDER BY RAND() LIMIT 4)
) t
WHERE t.id = t1.id AND t.category = t1.category
)
See the demo.
SELECT * FROM table1 where id not in (
select id from (
(SELECT * FROM table1 WHERE table1.category = 'A' ORDER BY RAND() LIMIT 4)
UNION ALL
(SELECT * FROM table1 WHERE table1.category = 'B' ORDER BY RAND() LIMIT 4)
)
as t)

Need to rewrite query to use max function in a where clause

Query being used at this time:
update metrics.time_created
set cumu_count = (
select count(*)
from perf_stats.time
where date(insert_datetime)='2015-12-18'
)
where id=max(id);
I get an "invalid use of group function" here -- how can I rewrite this to keep the same logic? I have to update the most recent row in the metrics.time_created table.
Try this:
update metrics.time_created a
set cumu_count = (
select count(*)
from perf_stats.time
where date(insert_datetime)='2015-12-18'
)
where exists (
select 1
from (select max(id) as maxid from metrics.time_created) t
where maxid = a.id
);
Example demo: http://sqlfiddle.com/#!9/6bc3cd/1
EDIT:
Based on comment, here's the change
update metrics.time_created a
set cumu_count =
(
select count(*)
from perf_stats.time pt
where exists
(
select 1
from (select max(curr_date) as mcd from metrics.time_created) x
where mcd = date(insert_datetime)
)
)
where exists
(
select 1
from (select max(id) as maxid from metrics.time_created) t
where maxid = a.id
);
Example demo: http://sqlfiddle.com/#!9/fcc91a/1
You can use self join something like this :
update metrics.time_created as t1
inner join (
select max(id) as id
from metrics.time_created
) as t2 on t1.id = t2.id
set cumu_count = (
select count(*)
from perf_stats.time
where date(insert_datetime)='2015-12-18'
)
If you are trying to update one row with the maximum id, then you can use order by and limit:
update metrics.time_created
set cumu_count = (select count(*)
from perf_stats.time
where date(insert_datetime) = '2015-12-18'
)
order by id desc
limit 1;

MySQL count across multiple tables and get single value

Imagine:
t1 = 1
t2 = 3
t3 = 5
I need to run individual selects on each table, and report the count in a single amount, ie:
select *
from (select count(*) from t1)
+ (select count(*) from t2)
+ (select count(*) from t3);
My end result should be = 9
You're pretty close; you can write:
select (select count(*) from t1)
+ (select count(*) from t2)
+ (select count(*) from t3)
;
select
(select count(*) from t1)
+ (select count(*) from t2)
+ (select count(*) from t3);