i am trying to write SELECT statement which would return some elements + date difference between current time and date_created or date_edited. If field was edited i should grab date_edited from other table which updates after editing element, if it was not i should grab date_created from current one because that element do not have relationship with other edited elements table, and calculate DATEDIFF(NOW(), date_created/date_edited). I have written select which brings me edited elements with correct date, and other select which brings all elements just if they were edited it brings me incorrect date difference. So all in all i need to form single table which brings me elements with calculated date difference.
SELECT
table1.name,
table1.sales_stage,
users.user_name,
DATEDIFF(NOW(), table1_edit.date_edited) as DaysOnStage
FROM table1
join users on table1.assigned_user_id = users.id
join table1_edit on table1.id = table1_edit.parent_id
WHERE table1.sales_stage = table1_edit.after_value_string;
This one brings all edited values with correct date calculated.
SELECT
table1.name,
table1.sales_stage,
users.user_name,
DATEDIFF(NOW(), table1.date_created) as DaysOnStage
FROM table1
join users on table1.assigned_user_id = users.id;
This one brings me all elements but if they were edited ofcourse with bad date difference. Need somehow to combine these selects and form single table.
Thanks in advance!
You can left join the edit table and put a ISNULL() (IFNULL() in mysql) function on the date field:
SELECT
table1.name,
table1.sales_stage,
users.user_name,
DATEDIFF(NOW(), IFNULL(table1_edit.date_edited,table1.date_created) as DaysOnStage
FROM table1
join users on table1.assigned_user_id = users.id
left join table1_edit on table1.id = table1_edit.parent_id
WHERE table1.sales_stage = table1_edit.after_value_string;
Left/Outer joining tables is a must-learn for working in SQL:
http://www.w3schools.com/sql/sql_join_left.asp
or you can use UNION with your queries:
SELECT
table1.name,
table1.sales_stage,
users.user_name,
DATEDIFF(NOW(), table1_edit.date_edited) as DaysOnStage
FROM table1
join users on table1.assigned_user_id = users.id
join table1_edit on table1.id = table1_edit.parent_id
WHERE table1.sales_stage = table1_edit.after_value_string;
This one brings all edited values with correct date calculated.
UNION
SELECT
table1.name,
table1.sales_stage,
users.user_name,
DATEDIFF(NOW(), table1.date_created) as DaysOnStage
FROM table1
join users on table1.assigned_user_id = users.id;
http://www.w3schools.com/sql/sql_union.asp
I think you can do what you want with a left join and then use COALESCE() to choose the right value:
SELECT t1.name, t1.sales_stage, u.user_name,
DATEDIFF(NOW(), COALESCE(te.date_edited, t1.date_created)) as DaysOnStage
FROM table1 t1 join
users u
on t1.assigned_user_id = u.id LEFT JOIN
table1_edit te
on t1.id = te.parent_id
WHERE t1.sales_stage = te.after_value_string;
if should be helpful
SELECT
table1.name,
table1.sales_stage,
users.user_name,
if (table1_edit.parent_id is null, DATEDIFF(NOW(), table1_edit.date_edited), DATEDIFF(NOW(), table1.date_created)) as DaysOnStage
FROM table1
join users on table1.assigned_user_id = users.id
left join table1_edit on table1.id = table1_edit.parent_id
enter code here
Related
In MySQL, how would you re-write a SELECT query which JOIN SELECT subqueries that are doing almost the same thing.
In my case, I am getting performance issues because in the subqueries, I need to join on the same tables for each subqueries which is an heavy operation.
Consider the below (ugly) example:
set #businessdate = '2020-01-24';
Select Daily.*, Monthly.Price, Yearly.Price FROM
# DAILY
(Select #businessdate as BusinessDate, t1.Owner , SUM(t.Price) AS DailyPrice
FROM Table t
INNER JOIN Table2 t2 on ...
INNER JOIN Table1 t1 on ...
where t2.date = #businessdate
GROUP BY t1.Owner) Daily
INNER JOIN
# MONTHLY
(Select SUM(t.Price) AS Price, t1.Owner
FROM Table t
INNER JOIN Table2 t2 on ...
INNER JOIN Table1 t1 on ...
where MONTH(t2.date) = MONTH(#businessdate) and YEAR(t2.date) = YEAR(#businessdate)
GROUP BY t1.Owner) Monthly
INNER JOIN
#YEARLY
(Select SUM(t.Price) AS Price, t1.Owner
FROM Table t
INNER JOIN Table2 t2 on ...
INNER JOIN Table1 t1 on ...
where YEAR(t2.date) = YEAR(#businessdate)
GROUP BY t1.Owner) Yearly
The reason is I need the date in my where clause (coming from t2), and one field in my group by coming from t1. I also need to display some fields from t1.
I only need the SUM(Price) (the Price from Monthly and Yearly...) so to me it sounds like the joins in subqueries is overkill even if it is working fine (very slow...)
You could use conditional aggregation with a single query:
Select
#businessdate as BusinessDate, ... ,
SUM(CASE WHEN t2.date = #businessdate THEN t.Price ELSE 0 END) AS DailyPrice,
SUM(CASE WHEN MONTH(t2.date) = MONTH(#businessdate) AND
YEAR(t2.date) = YEAR(#businessdate)
THEN t.Price ELSE 0 END) AS MonthlyPrice,
SUM(CASE WHEN YEAR(t2.date) = YEAR(#businessdate)
THEN t.Price ELSE 0 END) AS AnnualPrice
FROM Table t
INNER JOIN Table2 t2 on ...
INNER JOIN Table1 t1 on ...
GROUP BY t1.Owner
This at least would allow you to avoid unneeded passes over the joined tables. Note that your GROUP BY clause is invalid as written; the business date is the only valid single column which can be selected, other than the conditional sums.
Here’s the problem I am trying to solve:
Table1 has Product ID’s, dates, and prices for those dates, Table2 has Product attributes.
I want to be able to compare prices for a client for different products on the same date based on a set of attributes. I’m easily able to get a list of products/dates/prices for a ‘simple’ product, as well as an ‘advanced’ product (see below).
I want to be able to join these two tables such that the output looks like:
[CLIENT] [PRODUCT] [DATE] [SIM_PROD] [SIM_PRICE] [ADV_PROD] [ADV_PRICE]
Here is as far as I've made it
SELECT b.NAME AS ‘CLIENT’, a.NAME AS ‘SIMPLE_PRODUCT’, t1.DATE AS ‘DATE’, t1.PIVOT_PRICE AS ‘SIMPLE_PRICE’
FROM TABLE1 t1
LEFT JOIN PRODUCT a
ON t1.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = TRUE;
SELECT b.NAME AS ‘CLIENT’, a.NAME AS ‘ADV_PRODUCT’, t2.DATE AS ‘DATE’, t2.PIVOT_PRICE AS ‘ADV_PRICE’
FROM TABLE1 t2
LEFT JOIN PRODUCT a
ON t2.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = FALSE;
I've been able to build similar tables where I pull in price from TABLE1 labeling it as t1 then pull in price again from TABLE1 and labeling it as t2, but only when using criteria in TABLE1, not criteria in a table that needs to be joined.
Is it possible to 'set' a table (EG simple) then 'set' a second one (EG advanced) and then join them on PARTNER_ID and DATE?
You can join the two subqueries:
SELECT t1.client, t1.date, t1.simple_product, t1.simple_price, t2.adv_product, t2.adv_price
FROM (
SELECT b.NAME AS CLIENT, a.NAME AS SIMPLE_PRODUCT, t1.DATE, t1.PIVOT_PRICE AS SIMPLE_PRICE
FROM TABLE1 t1
LEFT JOIN PRODUCT a
ON t1.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = TRUE
) AS t1
JOIN (
SELECT b.NAME AS CLIENT, a.NAME AS SIMPLE_PRODUCT, t1.DATE, t1.PIVOT_PRICE AS SIMPLE_PRICE
FROM TABLE1 t1
LEFT JOIN PRODUCT a
ON t1.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = FALSE
) AS t2
ON t1.client = t2.client AND t1.date = t2.date
You'll probably need to select additional criteria and add them to the ON condition. Otherwise this will produce a full cross product between all the products that have the same client and date.
Your desired output has an additional PRODUCT column, but I couldn't see where that comes from.
After SELECT a table GROUP BY a field, I get a results, and then I LEFT JOIN the results with a table. Can I do that?
Thankyou!
You should be, try:
Select *
From(
SELECT *
FROM myTableOne
GROUP BY myCol1
) firstTable
LEFT JOIN myTableTwo secondTable ON
firstTable.idColumn = secondTable.idColumn
Where myTableOne is the group by selection and myTableTwo is the table you want to left join on
Hi I am trying to compare two tables based on two columns. I to see where the usernames match between the tables and the email addresses don't match.
Here is what I tried:
select * from ecy t1, users t2 where t1.username = t2.username and t1.email <> t2.email
When I run this I get all the users in the ecy table even if their emails are equal.
Thanks.
I wouldn't do the Cartesian Product of the two tables and try to filter it with the old Ansi way.
SELECT u.username, u.email
FROM users u
JOIN ecy e on e.email <> u.email AND u.username = e.username
you could also try doing it with a subquery select that is joined
SELECT username, email
FROM users u
JOIN( SELECT username, email FROM ecy) t on t.username = u.username and t.email <> u.email
DEMO
you want to use the JOIN syntax to join tables together and not do a Cartesian Product. the JOIN syntax will also allow you to filter out data as it joins
you can try this, i didn't use <> before in mysql.
select * from ecy t1, users t2 where t1.username = t2.username and not t1.email = t2.email
Trying to do an inner join on two composite tables, having trouble with the syntax. Here's what I have:
SELECT
count(*)
FROM
(
SELECT DISTINCT seller FROM Items, Users WHERE Items.seller = Users.userID t1
INNER JOIN
(
SELECT DISTINCT UserID FROM Bids, Users WHERE Bids.UserID = Users.userID
)
t2 ON t1.userID = t2.userID
)
I'm guessing it has something to do with the parantheses/lack of as/or whatever. I guess what I'm really asking here is how to give my subqueries aliases, but not using as in the FROM part. Is it valid just to have t1 after User.userID and identify that whole table as t1?
I think this is what you want?
SELECT count(*)
FROM Users
INNER JOIN Items ON Users.userID = Items.seller
INNER JOIN Bids ON Users.UserID = Bids.UserID
You want to name the output table which you get from query
SELECT DISTINCT seller FROM Items, Users WHERE Items.seller = Users.userID
as t1
simple way is use
`select * from (SELECT DISTINCT seller FROM Items, Users WHERE Items.seller = Users.userID)t1`