Notice that I'm calling and joining the same tables for my main query and subquery.
Now my actually query is using many more subqueries like that.
Is there a way to call a subquery field from the main query thus eliminating the need to reuse the same join tables in the subqueries? I want to make it more efficient without sacrificing speed.
SELECT tb1.id, tb1.title,
(SELECT tb1.title
FROM table1 AS tb1
JOIN table2 AS tb2 ON tb2.id = tb1.id
LEFT JOIN table3 AS tb3 ON tb2.id = tb3.id
WHERE tb1.id > '123' LIMIT 1) AS next
FROM table1 AS tb1
JOIN table2 AS tb2 ON tb2.id = tb1.id
LEFT JOIN table3 AS tb3 ON tb2.id = tb3.id
WHERE tb1.id='123'
You can use a View to abstract that query.
CREATE VIEW tbl_view AS
SELECT
tb1.id as id,
tb1.title as title
FROM table1 AS tb1
JOIN table2 AS tb2 ON tb2.id = tb1.id
LEFT JOIN table3 AS tb3 ON tb2.id = tb3.id
The shorter query would be
SELECT
id,
title,
(SELECT title FROM tbl_view
WHERE id > '123' LIMIT 1) AS next
FROM
tbl_view
WHERE id='123'
Related
I have a query which works correctly however I need to change the user in the where.
user1=012345
user2=12121
uer3=878787
select count(*) as xxx from(
select a,b,c from tb1 t1 left join tb2 t2 on t1.id=t2.rf
where t1.user='012345'
) as table
how do I dynamically change the where statement so that it evaluates the three users and gives me the results
How about in?
where t1.user in (user1, user2, user3)
This should help -
select t1.user, count(t1.user) count
from tb1 t1
left join tb2 t2 on t1.id = t2.rf
where t1.user in (012345, 12121, 878787)
group by t1.user
I have two tables table1 and table2. table1 has columns id and table2_id while table2 has id and category. I need to count rows from table1 based on two separate values in table2.category containing value Regular or Special.
I have done this in two queries but I want to know if it is possible in a single sql. My queries are:
"SELECT COUNT(t1.id) AS regular FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.t2_id = t2.id WHERE t2.category = 'Regular'";
"SELECT COUNT(t1.id) AS special FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.t2_id = pr.id WHERE t2.category = 'Special'";
Thanks.
EDIT
The second query JOIN should read ON t1.t2_id = t2.id and not ON t1.t2_id = pr.id. Sorry for the confusion that may have caused. Please update/edit your answers/comments accordingly.
Move the Where condition to CASE statement and do the counting
Here is one way using Conditional Aggregate
SELECT
COUNT(case when t2.category = 'Regular' then t1.id end) AS Regular,
COUNT(case when t2.category = 'Special' then t1.id end) AS special
FROM table1 t1
INNER JOIN table2 t2 ON t1.t2_id = pr.id
Where t2.category IN ('Regular','Special' )
Note : I have changed the LEFT JOIN to INNER JOIN because you want to count only when table2.category is 'Regular' or 'Special' so no use of LEFT JOIN here
Instead of
"SELECT COUNT(t1.id) AS regular FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.t2_id = t2.id WHERE t2.category = 'Regular'";
"SELECT COUNT(t1.id) AS special FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.t2_id = pr.id WHERE t2.category = 'Special'";
you can do this:
select t2.category, count(t1.id)
from table1 t1
left outer join table2
on t1.t2_id = t2.id
group by t2.category
having t2.category in ('Regular', 'Special')
The suggested query groups the joined records, filters the groups and selects the category name and its count.
here us the query
SELECT *
FROM Table1
WHERE complete='Y'
AND shipped='Y'
AND active='Y'
AND create_dttm > '2013-10-10 08:28:41'
AND order_id IN
(SELECT DISTINCT t1.order_id
FROM Table2 t1
INNER JOIN table3 t2 ON t1.prod_id = t2.prod_id
WHERE t2.prod_sku LIKE '%D-600%'
AND t1.create_dttm > '2013-02-15 08:28:41')
You are using a sub-query in WHERE clause, that could be the main reason behind slow execution of your query. Try using JOINS instead of sub query.
SELECT t1.*
FROM Table1 t1
INNER JOIN Table2 t2 ON T1.order_id = T2.order_id
AND t2.create_dttm > '2013-02-15 08:28:41'
INNER JOIN table3 t3 ON t2.prod_id = t3.prod_id
AND t3.prod_sku LIKE '%D-600%'
WHERE complete='Y'
AND shipped='Y'
AND active='Y'
AND create_dttm > '2013-10-10 08:28:41'
And also check for indexes on your tables.
I am currently using this script below.
$query = mysql_query("SELECT * FROM `venues` as table1
LEFT JOIN `follows` as table2 on table1.venue_id = table2.venue_id
WHERE table2.user_id = $userid");
The tables have these fields:
Table1:
id, venue_id, user_id...
Table2:
id, venue_id, user_id...
The query above returns 5 records.
Now....
I need to add a third table to the above script Table3
Table 3 fields also contains id, venue_id, user_id... BUT I don't what it in the WHERE of the script.
I've tried adding a LEFT JOIN to the script above to add the third table like this:
$query = mysql_query("SELECT * FROM `venues` as table1
LEFT JOIN `follows` as table2 on table1.venue_id = table2.venue_id
LEFT JOIN `stats` as table3 on table1.venue_id = table3.venue_id
WHERE table2.user_id = $userid");
The Stats table only contains 1 record.
Now, my problem is that the query above it's echoing the data on ALL the records and not just the one.
My question is...What I'm I doing wrong on the line I added:
LEFT JOIN stats as table3 on table1.venue_id = table3.venue_id ?
OK, I think you want to also join on the user_id. So
SELECT
*
FROM
`venues` AS table1
LEFT JOIN `follows` AS table2 USING (venue_id)
LEFT JOIN `stats` AS table3 USING (venue_id, user_id)
WHERE
table2.user_id = $userid
is my solution
If you only want to include record from table1 that have non null records in table3 then you need to use INNER JOIN and not a LEFT JOIN. See the MySQL documentation for JOIN
$query = mysql_query("SELECT * FROM `venues` as table1
LEFT JOIN `follows` as table2 on table1.venue_id = table2.venue_id
INNER JOIN `stats` as table3 on table1.venue_id = table3.venue_id
WHERE table2.user_id = $userid");
The "INNER" is not needed explicitly. Joins are INNER joins by default
You're not limiting the records at all. Use this instead:
$query = mysql_query("SELECT * FROM `venues` as table1
LEFT JOIN `follows` as table2 on table1.venue_id = table2.venue_id
LEFT JOIN `stats` as table3 on table1.venue_id = table3.venue_id
WHERE table2.user_id = $userid AND table3.venue_id IS NOT NULL");
You can use an INNER JOIN rather than an LEFT JOIN. See this SO post to make it clear or this blog article
I have the following SQL query:
SELECT * FROM `table1` INNER JOIN `table2` ON table1.messageid=table2.messageid WHERE `venue_active` = 1
The above works fine but it only returns fields where both tables have a messageid field.
My problem is that I need it to return ALL fields from Table1 reguardless if it has a messageid match in table2 or not.
So, in other words I need ALL records to be returned from Table1 and all records from Table2 where there's a messageid that matches both.
How can I do this?
Use a LEFT JOIN rather
SELECT *
FROM `table1` LEFT JOIN
`table2` ON table1.messageid=table2.messageid
WHERE `venue_active` = 1
That said, it will only work if venue_active is also part of table1, and not table2.
Have a look at the different scenarios
SQL Fiddle DEMO
Use a LEFT join rather than INNER
For example:
SELECT * FROM `table1`
LEFT JOIN `table2` ON table1.messageid=table2.messageid
WHERE `venue_active` = 1
Either you need a LEFT JOIN instead, or
a FULL OUTER JOIN workaround for MySQL:
SELECT
a.*,
b.*
FROM
table1 a
LEFT JOIN
table2 b ON a.messageid = b.messageid
WHERE a.venue_active = 1
UNION
SELECT
a.*,
b.*
FROM
table1 a
RIGHT JOIN
table2 b ON a.messageid = b.messageid;
WHERE a.venue_active = 1