Thanks for looking at my post, any help/guidance is appreciated. My SQL skills are lacking and I have tried several solutions without success. Anyway, I need to create a VIEW for the following query:
CREATE VIEW open_orders AS
SELECT
t1.orderID,
DATE_FORMAT(t1.orderDate,'%m-%d-%Y') AS orderDate,
t6.colorName,
t1.originID,
t1.rackNumber,
t2.locationNumber AS originNumber,
t2.locationName AS originName,
t3.locationName AS destinationName,
t4.locationStatusName,
COUNT(t5.orderID) AS totalCount
FROM `order` AS t1
JOIN `location` AS t2 ON t1.originID = t2.locationID
JOIN `location` AS t3 ON t1.destinationID = t3.locationID
JOIN `locationStatus` AS t4 ON t1.locationStatusID = t4.locationStatusID
LEFT JOIN (SELECT * FROM `orderItem` WHERE `productStatusID` = 02 OR `productStatusID` = 03) AS t5 ON t1.orderID = t5.orderID
JOIN `color` AS t6 ON t1.requestedColorID = t6.colorID
WHERE t1.orderStatusID = 01
GROUP BY t1.orderID
ORDER BY t1.orderDate DESC, t1.orderID DESC;
The problem is with the subquery. Because I can't use a subquery within the FROM statement I attempted to use a VIEW. However, the table is large and this approach causes too much of a performance issue.
I'm sure there is a way I can accomplish this without using a VIEW or subquery but am having trouble coming up with a solution.
Any help/guidance is appreciated.
You don't need a subquery.
...
LEFT JOIN orderItem AS t5
ON t5.orderID = t1.orderID
AND t5.productStatusID IN (02,03)
JOIN color ...
This does the same thing as your query, but more efficiently since it avoids the derived table.
Related
How to implement WHERE conditions in LEFT_JOIN. My query is:
SELECT t1.company_short_name, COUNT(t2.user_ip_address) as chart_accessed
FROM tblcompanymaster t1
LEFT JOIN tblhistorymaster t2 ON t1.row_id = t2.company_id
WHERE t2.user_last_request_time BETWEEN 1603775329 AND 1606280929
GROUP BY t1.company_short_name
Where I need to found all the company_short_name with the count of access, and if there is no access or the count is 0 then it should come COUNT(t2.user_ip_address) is 0. When I am not using where condition its working perfectly but after the use of where condition its giving only the result where the count is greater then 1. I have tried a lot but I am not able to modify the code. Any suggestions will be of great help
Put your where clause condition to ON clause
SELECT t1.company_short_name, COUNT(t2.user_ip_address) as chart_accessed
FROM tblcompanymaster t1
LEFT JOIN tblhistorymaster t2 ON t1.row_id = t2.company_id
and t2.user_last_request_time BETWEEN 1603775329 AND 1606280929
GROUP BY t1.company_short_name
You can add the filtering (where) component to the join instead - only taking the values if they exist in t2.
SELECT t1.company_short_name, COUNT(t2.user_ip_address) as chart_accessed
FROM tblcompanymaster t1
LEFT JOIN tblhistorymaster t2 ON t1.row_id = t2.company_id AND t2.user_last_request_time BETWEEN 1603775329 AND 1606280929
GROUP BY t1.company_short_name
I am trying to compare values against same table which has more than 1,000,000 rows. Below is my query and it takes around 25 secs to get results.
EXPLAIN SELECT DISTINCT a.studyid,a.number,a.load_number,b.studyid,b.number,b.load_number FROM
(SELECT t1.*, buildnumber,platformid FROM t t1
INNER JOIN testlog t2 ON t1.`testid` = t2.`testid`
WHERE (buildnumber =1031719 AND platformid IN (SELECT platformid FROM platform WHERE platform.`Description` = "Windows 7 SP1"))
)AS a
JOIN
(SELECT t1.*,buildnumber,platformid FROM t t1
INNER JOIN testlog t2 ON t1.`testid` = t2.`testid`
WHERE (buildnumber =1030716 AND platformid IN (SELECT platformid FROM platform WHERE platform.`Description` = "Windows 7 SP1"))
)AS b
ON a.studyid=b.studyid AND a.load_number = b.load_number AND a.number = b.number
Could you anyone help me to improve this query to get fast enough results?
The problem here is even I have number and load_number index, the query doesn't use that. I dont know why it is always ignored..
Thanks.
First, you have a silly query. You are retrieving six columns, but there are only three values. Look at the on clause.
I think your best bet is to rewrite the query using conditional aggregation. I think the following is equivalent:
SELECT t1.studyid, t1.load_number, t1.number
FROM t t1 INNER JOIN
testlog t2
ON t1.testid = t2.testid
WHERE t2.buildnumber IN (1031719, 1030716) AND
platformid IN (SELECT platformid FROM platform p WHERE p.Description = 'Windows 7 SP1'))
GROUP BY studyid, load_number, number
HAVING MIN(buildnumber) <> MAX(buildnumber)
For this query, you want indexes on platform(Description, platformid) and testlog(buildnumber, platformid) and t(testid).
Problem #1:
IN ( SELECT ... ) optimizes very poorly. The subquery is rerun again and again. It looks like you are expecting exactly one id from that query; if so, change it to = ( SELECT ... ). That way it will be run exactly once.
Problem #2:
FROM ( SELECT ... )
JOIN ( SELECT ... ) ON ...
optimizes poorly because neither subquery. Can you merge the two subqueries into one, as Gordon was trying? If not, then put one of them into a TEMPORARY TABLE and add an appropriate index to that table so that the ON will be able to use it. Probably PRIMARY KEY(studyid, load_number, number).
Footnote: The latest versions of MySQL have made improvements on these problems by dynamically generating indexes. What version are you using?
I think my title says it all, but in essence, this is what I want to do:
SELECT t1.*, t2.friendly_name, CONCAT_WS(" ",t3.name,t3.surname) AS user FROM activity
LEFT JOIN t1.typedb AS t2 ON t1.typeid = t2.id
LEFT JOIN users AS t3 on t1.loginid = t2.loginid
ORDER BY time DESC, user ASC
But as you can imagine, this will give me an error.
I can do a normal select on the activity db and then do a loop in php and run queries to fetch the info. But there has to be a way to do this in one query in MYSQL.
Please help.
So there is a table name in typedb? Then no, SQL doesn't support this. This is not how a relational database is supposed to work.
You can try something along the lines of
SELECT
t1.*,
coalesce(x1.friendly_name, x2.friendly_name, x3.friendly_name) as friendly_name,
CONCAT_WS(" ",t3.name,t3.surname) AS user
FROM activity t1
LEFT JOIN tableX AS x1 ON t1.typeid = x1.id and t1.typedb = 'TABLEX'
LEFT JOIN tableY AS x2 ON t1.typeid = x2.id and t1.typedb = 'TABLEY'
LEFT JOIN tableZ AS x3 ON t1.typeid = x3.id and t1.typedb = 'TABLEZ'
LEFT JOIN users AS t3 on t1.loginid = coalesce(x1.loginid,x2.loginid,x3.loginid)
ORDER BY time DESC, user ASC;
But this is not very efficient. It's just not what SQL is made for. So use a programming language and build dynamic SQL, or even better: change your database design.
It's been a long time since I last did something with database so my knowledge has beenyet rusted. I have 2 SQL tables:
data(id, attr);
dependency(child, parent);
#**child** and **parent** are the id from table **data**
I need to query all the attr corresponding to the entries in table dependency. Following is my attempt:
SELECT
(SELECT data.attr FROM data WHERE data.id = child) AS child_attr,
(SELECT data.attr FROM data WHERE data.id = parent) AS parent_attr
from dependency;
It works but very slow. I'm sure there's a better way to do it with join query but cannot come up with it yet.
Can someone please help?
Thanks,
You could join the dependency table to the data table twice to get the information you need:
SELECT d1.attr AS ChildAttr, d2.attr AS ParentAttr
FROM dependency AS dep
INNER JOIN data AS d1 ON dep.child = d1.id
INNER JOIN data AS d2 ON dep.parent = d2.id
try this:
SELECT t2.attr, t3.attr
FROM dependency as t1
INNER JOIN data as t2 on t1.child = t2.id
INNER JOIN data as t3 on t1.parent = t3.id
I have query that working perfectly.but now there is situation where i have to join 2 query in case statement.but problem is one of the query is in already use.So my question how do i add this two sql in one sql
My original sql is
SELECT
tc.dentist_id,md.vendor_no,pl.pack_trans_id,tc.agent_dentist,md.company_name,md.contact,md.phone_no,sql1.image_path,sql1.metal_id,sql1.expect_more,sql1.how_long_acquire,tc.check_amt,tc.check_date_sent,tc.check_no
FROM tbl_check tc
LEFT JOIN tbl_mst_dentist md ON tc.dentist_id=md.dentist_id
LEFT JOIN tbl_pack_list pl ON tc.pack_id=pl.pack_id
LEFT JOIN (SELECT image_path,pack_id,metal_id,expect_more,how_long_acquire FROM
tbl_metals_list GROUP BY pack_id
)sql1 ON tc.pack_id=sql1.pack_id
WHERE tc.sale_agent_id = '3' AND tc.paying_percent !=0
Now i have to add 2 sql statement in the above statement
if(tc.agent_dentist=a) select sa.* ,sm.state_code from tbl_sales_agent
as sa,tbl_mst_state as sm where sa.sales_agent_id = '3' AND
sa.state=sm.state_name else select * from tbl_mst_dentist where
dentist_id =tc.dentist_id
second table already is in use.Is it possible? Thanks in advance
yes, you can use an ALIAS with a different name. E.g. TABLE AS ANY_ALIAS.
SELECT *
FROM t1
JOIN t2 AS alias_a ON (alias_a.t1_id = t1.id)
JOIN t2 AS alias_b ON (alias_b.t1_id = t1.id)
Note that in the absence of any aggregating functions, the use of GROUP BY in this query...
SELECT image_path
, pack_id
, metal_id
, expect_more
, how_long_acquire
FROM tbl_metals_list
GROUP
BY pack_id
...makes little sense. Perhaps you meant SELECT DISTINCT...?