I am fetching the result of Union All but Only 1 query is running.
select user_leftside as SId from tbl_user inner join (select #sid:=(select group_concat(user_leftside,',',user_rightside) from tbl_user where find_in_set(user_id, #nsid)) , #nsid:=#sid as fset from tbl_user, (select #nsid:='first_left_child',#sid='')v )gr on find_in_set(user_leftside,fset) where user_leftside <> ''
UNION ALL
select user_rightside as SId from tbl_user inner join (select #sid:=(select group_concat(user_leftside,',',user_rightside) from tbl_user where find_in_set(user_id, #nsid)) , #nsid:=#sid as fset from tbl_user, (select #nsid:='first_left_child',#sid='')v )gr on find_in_set(user_rightside,fset) where user_rightside <> ''
How can i get the result with Union All. This is tree related query
Use different variable names inside those two subqueries.
The use of variables in MySQL queries is always risky: the order of evaluation is not guaranteed. These subqueries might even perform evaluations in parallel and so you must avoid spillover of variable values from one to the other.
Related
I want the count even if the count is 0. My current query is
SELECT `id`,count(0) as `fetchpc` FROM `user` WHERE pid in('4,6,7,8') GROUP BY `id`
But it returns only those id where count is greater than 0
Edit:
the values used for in('4,6,7,8') are first fetched from database in another query. And then using a script rows are converted to 4,6,7,8.
So all the values are present in the database.
Also it is possible that the values returned can go upto 100+ values.
You could left join this query on a "fictive" query that queries these IDs as literals:
SELECT ids.id, COALESCE(cnt, 0)
FROM (SELECT 4 AS id
UNION ALL
SELECT 6 AS id
UNION ALL
SELECT 7 AS id
UNION ALL
SELECT 8 AS id) ids
LEFT JOIN (SELECT id, COUNT(*) AS cnt
FROM fetchpc
GROUP BY id) t ON t.id = ids.id
You can use a derived table. I would recommend:
SELECT i.id, COUNT(u.id) as fetchpc
FROM (SELECT 4 as id UNION ALL
SELECT 6 as id UNION ALL
SELECT 7 as id UNION ALL
SELECT 8 as id
) i LEFT JOIN
`user` u
ON u.id = i.id
GROUP BY i.id;
From a performance perspective, this is much better than aggregating first (in a subquery) and then joining. Basically, the aggregation (in that case) has to aggregate all the data and afterwards filter out the unnecessary rows.
This formulation filters the rows first, which should speed the aggregation.
Can I have a mysql query where I get the count of rows, value equal to a row of same table.
Please check my below query and Can I optimize it. It's taking very long time to load
SELECT CASE
WHEN
table1.issue_type = 'email'
THEN
(SELECT Count(tabl1a.id) FROM table1 AS table1a WHERE table1a.email = table1.email)
ELSE
(SELECT Count(table1a.id) FROM table1 AS table1a WHERE table1a.phone_day = table1.phone_day)
END
AS emails
FROM table1
Advice me please
The usual remedy for such correlated subqueries in a select clause is to refactor by instead joining to a subquery which performs the aggregation. In this case, there are actually two different aggregations which you are doing, so we can left join to two subqueries to perform the aggregations.
SELECT
t1.issue_type,
COALESCE(t2.email_cnt, t3.phone_cnt) AS emails
FROM table1 t1
LEFT JOIN
(
SELECT email, COUNT(*) AS email_cnt
FROM table1
GROUP BY email
) t2
ON t1.email = t2.email AND
t1.issue_type = 'email'
LEFT JOIN
(
SELECT phone_day, COUNT(*) AS phone_cnt
FROM table1
GROUP BY phone_day
) t3
ON t1.phone_day = t3.phone_day AND
t1.issue_type <> 'email'
The trick here to add a condition to the join criteria checking whether or not the issue type is email. This guarantees that each record in your table will join to one and only one subquery. We use COALESCE to choose the non NULL count, coming from either the email or phone day aggregation.
I have a weird situation. I need to select all data from table name with distinct values from other table.
Here is database scheme of database that I need to get distinct values:
When I run both queries without INNER JOIN they run without error but when I use INNER JOIN I got error
This is query that I used:
SELECT * FROM `todo`
INNER JOIN
SELECT `task`.`status`,COUNT(*) as count FROM `task`
ON `todo`.`id`=`task`.`id_list` WHERE `todo`.`user_id` = 43
As you can see I need to get total count of status column from other table. Can it be done using one single query or do I need to run two querys to get data...
You need to wrap the join In parenthesis
SELECT td.*, t.*
FROM `todo` td
JOIN
( SELECT `status`, SUM(status=0) as status_0, SUM(status=1) as status_1 , id_list
FROM `task`
GROUP BY id_list
) t ON td.id= t.id_list
WHERE td.user_id = 43
You can do this in one query. Even without a subquery:
SELECT ta.status, COUNT(*) as count
FROM todo t INNER JOIN
task ta
ON t.id = ta.id_list
WHERE t.user_id = 43
GROUP BY ta.status;
EDIT:
If the above produces what you want, then you probably need:
SELECT t.*, ta.status, taa.cnt
FROM todo t INNER JOIN
task ta
ON t.id = ta.id_list INNER JOIN
(SELECT count(*) as cnt, ta.status
FROM task ta
GROUP BY ta.status
) taa
on ta.status = taa.status
WHERE t.user_id = 43 ;
You seem to want a summary at the status level, which is only in task. But you want the information at the row level for todo.
I have a "server" table which has a column named 'SN' in mysql, when do query to retrive servers with some sns from 'sn1' to 'sn10000', we can:
select * from server where sn in ('sn1','sn2','sn3',...'sn10000');
If there is only one sn in 'sn1'-'sn10000' which not exists in database, then the query above will retrive 9999 rows of result.
The question is how can I easily get which one in 'sn1'-'sn10000' is not exists in database except the additional work, such as handling the result with shell script etc.
I have an ugly sql like below can use:
select * from (select 'sn1' as sn
union select 'sn2'
union select 'sn3'
....
union select 'sn10000') as SN
where not exists (select id from server where server.sn=SN.sn);
Is Anyone has other better methods? Thanks.
Your query is perfectly fine for the intended use, but on MySQL the NOT IN and LEFT JOIN/IS NULL are more effecient that NOT EXISTS. Here are your alternatives:
NOT IN
SELECT *
FROM ( SELECT 'sn1' as sn
UNION ALL SELECT 'sn2'
UNION ALL SELECT 'sn3'
....
UNION ALL SELECT 'sn10000') as SN
WHERE sn.sn NOT IN (SELECT s.id FROM SERVER s)
LEFT JOIN/IS NULL
SELECT s.id
FROM SERVER s
LEFT JOIN ( SELECT 'sn1' as sn
UNION ALL SELECT 'sn2'
UNION ALL SELECT 'sn3'
....
UNION ALL SELECT 'sn10000') as SN ON SN.sn = s.id
WHERE sn.sn IS NULL
You might notice I used UNION ALL, rather than UNION - UNION removes duplicates (which won't happen in your example), making it slower so UNION ALL is a better choice.
Stick your sn1, sn2, sn3... sn10000 values in a temporary table, and then use Joins.
Select server.* from server inner join tempt on (tempt.value = server.sn)
will give you the ones that match, where as
Select sn.* from server right outer join tempt on (tempt.value = server.sn)
where server.somefield is Null
should take care of finding the missing ones.
I am generating a report in php (mysql),
ex:
`select count(id) as tot_user from user_table
select count(id) as tot_cat from cat_table
select count(id) as tot_course from course_table`
Like this I have 12 tables.
Can i make it in single query. If i did? Process gets slow?
SELECT (
SELECT COUNT(*)
FROM user_table
) AS tot_user,
(
SELECT COUNT(*)
FROM cat_table
) AS tot_cat,
(
SELECT COUNT(*)
FROM course_table
) AS tot_course
If you use MyISAM tables, the fastest way is querying directly the stats:
select table_name, table_rows
from information_schema.tables
where
table_schema='databasename' and
table_name in ('user_table','cat_table','course_table')
If you have InnoDB you have to query with count() as the reported value in information_schema.tables is wrong.
You can certainly us the a Select Agregation statement as Postulated by Ben James, However This will result in a view with as many columns as you have tables. An alternate method may be as follows:
SELECT COUNT(user_table.id) AS TableCount,'user_table' AS TableSource FROM user_table
UNION SELECT COUNT(cat_table.id) AS TableCount,'cat_table' AS TableSource FROM cat_table
UNION SELECT COUNT(course_table.id) AS TableCount, 'course_table' AS TableSource From course_table;
The Nice thing about an approch like this is that you can explicitly write the Union statements and generate a view or create a temp table to hold values that are added consecutively from a Proc cals using variables in place of your table names. I tend to go more with the latter, but it really depends on personal preference and application. If you are sure the tables will never change, you want the data in a single row format, and you will not be adding tables. stick with Ben James' solution. Otherwise I'd advise flexibility, you can always hack a cross tab struc.
select RTRIM(A.FIELD) from SCHEMA.TABLE A where RTRIM(A.FIELD) = ('10544175A')
UNION
select RTRIM(A.FIELD) from SCHEMA.TABLE A where RTRIM(A.FIELD) = ('10328189B')
UNION
select RTRIM(A.FIELD) from SCHEMA.TABLE A where RTRIM(A.FIELD) = ('103498732H')
SELECT t1.credit,
t2.debit
FROM (SELECT Sum(c.total_amount) AS credit
FROM credit c
WHERE c.status = "a") AS t1,
(SELECT Sum(d.total_amount) AS debit
FROM debit d
WHERE d.status = "a") AS t2
I know this is an old stack but i will post this Multi-SQL select case
SELECT bp.bizid, bp.usrid, bp.website,
ROUND((SELECT SUM(rating) FROM ratings WHERE bizid=bp.bizid)/(SELECT COUNT(*) FROM ratings WHERE bizid=bp.bizid), 1) AS 'ratings',
(SELECT COUNT(*) FROM bzreviews WHERE bizid=bp.bizid) AS 'ttlreviews',
bp.phoneno, als.bizname,
(SELECT COUNT(*) FROM endorsment WHERE bizid=bp.bizid) AS 'endorses'
, als.imgname, bp.`location`, bp.`ownership`,
(SELECT COUNT(*) FROM follows WHERE bizid=bp.bizid) AS 'followers',
bp.categories, bp.openhours, bp.bizdecri FROM bizprofile AS bp
INNER JOIN alluser AS als ON bp.usrid=als.userid
WHERE als.usertype='Business'