Where IN to JOIN how? - mysql

Writing down this using JOIN ..how?
because this is very slow..
SELECT *
FROM table1
WHERE ID IN (SELECT ID
FROM table1
GROUP BY ID
HAVING COUNT(*) = 2
AND MAX(awaiting) = 1)
AND awaiting = 1
so, how can I write?

Here is the join version:
SELECT t1.*
FROM table1 t1 join
(SELECT ID
FROM table1
GROUP BY ID
HAVING COUNT(*) = 2 AND MAX(awaiting) = 1
) tsum
on t1.id = tsum.id
WHERE t1.awaiting = 1

SELECT t1.*
FROM table1 AS t1
INNER JOIN
(
SELECT ID
FROM table1
GROUP BY ID
HAVING COUNT(*) = 2
AND MAX(awaiting) = 1
) AS t2 ON t1.ID = t1.ID AND t1.awaiting = t2.awaiting
WHERE t1.awaiting = 1;

I guess awaiting is 0 or 1. If so in your inner query MAX(awaiting) = 1 is redundant because of WHERE statement awaiting = 1
Also in this case you can use the following query.
SELECT *
FROM table1 as T1
WHERE
awaiting = 1
AND
(SELECT count(*) FROM table1 WHERE ID=T1.ID)=2

Related

How to select the id with max value that in another table

Here are 2 tables.
Table 1
id value
1 3
2 2
3 3
4 1
5 4
6 3
Table 2
id
1
3
4
How do I get the ids that are in Table 2 which have the max value in Table 1?
Output:
id
1
3
I already tried the following to get the max value, but I cannot figure out how to use it in a single query to get the matching rows. Because I think I need to select from the same table I just inner joined.
select max(table1.value)
from table2
inner join table1 on table1.id = table2.id;
Here is one method:
select t2.id
from (select t2.*, rank() over (order by value desc) as seqnum
from table2 t2 join
table1 t1
on t2.id = t1.id
) t
where seqnum = 1;
Or, an alternative that puts all the ids on one row:
select group_concat(t2.id) as ids
from table2 t2 join
table1 t1
on t2.id = t1.id
group by t1.value
order by t1.value desc
limit 1;
You have a couple of options available without using window functions:
You can use a WHERE clause to select only id values that have a value equal to the MAX(value) from your query and an id that is in Table2:
SELECT t1.id
FROM Table1 t1
WHERE value = (
SELECT MAX(t1.value)
FROM Table2 t2
JOIN Table1 t1 ON t1.id = t2.id
)
AND id IN (SELECT id FROM Table2)
You can JOIN your query to Table1 and Table2 again, matching the value in Table1 and the id in Table2:
SELECT t1.id
FROM (
SELECT MAX(t1.value) AS max_value
FROM Table2 t2
JOIN Table1 t1 ON t1.id = t2.id
) t
JOIN Table1 t1 ON t1.value = t.max_value
JOIN Table2 t2 ON t2.id = t1.id
In both cases the output is
id
1
3
Demo on SQLFiddle
Too low to comment but from the SQL statement you gave, you just need to add the tableid in your select parameters.
select table2.id, max(table1.value)
from table2
inner join table1 on table1.id = table2.id;

How to use 'group by' while having a sub query in MySQL?

I have the following query:
SELECT c.text1, sum(c.num1), sum(c.num2), sum(c.num3),
(SELECT count(id) FROM table2 WHERE type = 1 AND txt = c.text1 AND spec_id = c.sp_id)
FROM table1 as c
WHERE c.type = 1
GROUP BY c.text1, c.sp_id
Is there a workaround to loose the c.sp_id from the GroupBy clause somehow? I know that if I remove it MySQL will return an error.
Or is there a way to group the results of this query by c.text1 only?
If I understand the problem correctly, you need to do two separate aggregations. This is one version of the query:
SELECT c.text1, c.sum1, c.sum2, c.sum3, t2.cnt
FROM (SELECT c.text1, sum(c.num1) as sum1, sum(c.num2) as cum2, sum(c.num3) as sum3
FROM table1 c
GROUP BY c.text1
) c LEFT JOIN
(SELECT txt, count(*) as cnt
FROM table2 t2
WHERE t2.type = 1 AND
EXISTS (SELECT 1
FROM table1 c2
WHERE t.txt = c2.txt AND c2.type = 1 AND
t.spec_id = c2.sp_id
)
) t2
ON t2.txt = c.text1
WHERE c.type = 1;

Left join query

I have the following query
SELECT table1.*,
table2.status
FROM table1
LEFT JOIN table2 ON table1.transactionid = table2.transactionid
WHERE table2.transactionid IS NULL --Doesn't exist in table2
OR table2.status = 2
It returns me the table1 row if there isn't any row under the same transactionid in table2 or there is a row but it has status = 2 (error)
Now i need to modify it to don't return any table1 rows if there is a row with the same transactionid and status = 1 (completed) in table2
So, there can be multiple error rows but if there is one that is completed then i shouldn't get any result
Thank you
Not exists comes to mind:
SELECT t1.*
FROM table1 t1
WHERE NOT EXISTS (SELECT 1
FROM table2
WHERE t1.transactionid = t2.transactionid AND
t2.status = 1
);
Using 'NOT IN'
SELECT t1.*
FROM table1 t1
WHERE t1.transactionid NOT IN (SELECT t2.transactionid
FROM table2 t2
WHERE t1.transactionid = t2.transactionid AND
t2.status = 1
);
OR USING LEFT JOIN
SELECT t1.*
FROM table1 t1
LEFT JOIN table2 t2
ON t1.transactionid = t2.transactionid
WHERE t2.transactionid IS NULL

Limit on multiple table union

I've this mysql query with a limit on each select, but I want a limit of 1 on the complete query too. I've tried to build a Select around the whole query too, but it still goes through all the tables, even if there's a result in the first one so the duration is the same. I want the query to stop as soon as it gets a result. Is there any solution for this?
(SELECT count(*) FROM table1 i JOIN table1item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table2 i JOIN table2item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table3 i JOIN table3item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table4 i JOIN table4item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table5 i JOIN table5item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table6 i JOIN table6item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table7 i JOIN table7item it where it.columnId = 2 LIMIT 1)
Add UNION ALL to be sure you'll get results from all table if they are equal.
(SELECT count(*) FROM table1 i JOIN table1item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table2 i JOIN table2item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table3 i JOIN table3item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table4 i JOIN table4item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table5 i JOIN table5item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table6 i JOIN table6item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table7 i JOIN table7item it where it.columnId = 2)
LIMIT 1
A workmate found a solution which really reduces the query time (0.25 instead of 0.75 in my test case):
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else 0
end as result
FROM table1 i JOIN table1item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table2 i JOIN table2item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table3 i JOIN table3item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table4 i JOIN table4item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table5 i JOIN table5item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table6 i JOIN table6item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table7 i JOIN table7item it where it.fooId = 1 LIMIT 1

Return 0 if no row/empty result in mysql

is there a way where I can return 0 if i get an empty result in mysql?
SELECT t1.amount as Amt
FROM table1 as t1
INNER JOIN table2 as t2
ON t1.project_id = t2.id
WHERE t2.proj_name = "Project_Kalinga"
AND t1.date_sent = (SELECT MAX(date_sent) FROM table WHERE project_id = "0123")
Currently for the project name 'Project Kalinga' I get an empty result.
Is there a way where from this query even if i get an empty result, I'll just get 0 instead?
So then the output would be like
| Amt |
| 0 |
Thank You!
Here's the sqlfiddle
http://sqlfiddle.com/#!2/0c4c5/2
You can
create a "Dummy row" with zero
do a left join to your main query.
Coalesce the real value and the dummy value
SELECT Coalesce(t1.amt, d.amount) AS amt
FROM (SELECT 0 as amount
FROM DUAL) AS d
LEFT JOIN
(SELECT t1.amount AS Amt
FROM table1 AS t1
INNER JOIN table2 AS t2
ON t1.project_id = t2.id
WHERE t2.proj_name = "project_kalinga"
AND t1.date_sent = (SELECT Max(date_sent)
FROM table1
WHERE project_id = "0123")) AS t1
ON 1 = 1
Demo
Try this:
SELECT IFNULL(t1.amount,0) as Amt
FROM table t1
LEFT OUTER JOIN table2 t2
ON t1.project_id = t2.id AND t2.proj_name = "Project_Kalinga"
WHERE t1.date_sent = (SELECT MAX(date_sent) FROM table WHERE project_id = "0123")