SQL QUERY double full join and a nested join - mysql

I have been struggling to make a single sql query that would give the result of all 3 queries in one. I suppose I would need to use full joins.
These 3 queries are all grouped by hour_key and store_id and ordered by hour_key.
The 3 queries are the following :
select SUM(qty_invoiced) as diag, DATE_FORMAT(a.created_at, '%Y-%m-%d-%h') as hour_key, b.store_id
from sales_flat_order_item a inner join
sales_flat_order b
on (a.order_id = b.entity_id)
where a.created_at BETWEEN (NOW() - INTERVAL 7 DAY) AND NOW() AND
a.parent_item_id IS NULL AND
a.sku LIKE 'D-%' AND b.status in ('processing', 'complete', 'printed', 'ready_to_print', 'ready_to_ship')
GROUP BY DATE_FORMAT(a.created_at, '%Y-%m-%d-%h'), b.store_id
ORDER BY hour_key DESC
select SUM(grand_total) as grand_total, store_id , DATE_FORMAT(created_at, '%Y-%m-%d-%h') as hour_key, SUM(shipping_amount) as shipping
from sales_flat_order
where created_at BETWEEN (NOW() - INTERVAL 7 DAY) AND NOW() AND status in ('processing', 'complete', 'printed', 'ready_to_print', 'ready_to_ship')
GROUP BY DATE_FORMAT(created_at, '%Y-%m-%d-%h'), store_id
ORDER BY hour_key DESC
SELECT COUNT(a.entity_id) as totalPaniers, a.store_id, DATE_FORMAT(a.created_at, '%Y-%m-%d-%h') as hour_key
FROM sales_flat_quote a
WHERE a.created_at BETWEEN (NOW() - INTERVAL 7 DAY) AND NOW()
GROUP BY DATE_FORMAT(a.created_at, '%Y-%m-%d-%h'), a.store_id
ORDER BY hour_key DESC

We don't know what your table structure is, so my best guess is
SELECT
DATE_FORMAT(a.created_at, '%Y-%m-%d-%h') as hour_key,
COUNT(entity_id) as totalPaniers,
store_id,
SUM(grand_total) as grand_total,
SUM(shipping_amount) as shipping,
SUM(qty_invoiced) as diag
FROM
sales_flat_quote a
[LEFT] JOIN sales_flat_order b ON a.store_id=b.store_id
INNER JOIN sales_flat_order_item c ON c.order_id=b.entity_id
WHERE
a.created_at BETWEEN (NOW() - INTERVAL 7 DAY) AND NOW()
AND b.created_at BETWEEN (NOW() - INTERVAL 7 DAY) AND NOW()
AND c.created_at BETWEEN (NOW() - INTERVAL 7 DAY) AND NOW()
AND b.`status` IN ('processing', 'complete', 'printed', 'ready_to_print', 'ready_to_ship')
AND c.parent_item_id IS NULL
AND c.sku LIKE 'D-%'
GROUP BY
b.created_at, store_id
ORDER BY hour_key DESC

Related

present and absent in one query using mysql

I have following mysql query:
SELECT m.emp_id AS `Empid`
, d.dt AS `AbsentDate`,
(CASE WHEN p.punch_status IS NULL
THEN 'A'
ELSE p.punch_status
END
) s
FROM ( SELECT DATE(t.added_date) AS dt
FROM pmc_attendance t
WHERE date(t.added_date) >= '2018-08-01'
AND date(t.added_date) < DATE_ADD( '2018-08-31' ,INTERVAL 1 DAY)
GROUP BY DATE(t.added_date)
ORDER BY DATE(t.added_date)
) d
CROSS
JOIN tbl_admin_users m
LEFT
JOIN pmc_attendance p
ON date(p.added_date) >= d.dt
AND date(p.added_date) < d.dt + INTERVAL 1 DAY
AND p.emp_id = m.emp_id
WHERE p.emp_id IS NULL and m.emp_id='000838' group by d.dt
ORDER
BY m.emp_id
, d.dt
this would fetch all the absent records of the employee but i want to show present dates of employees also.
enter image description here
my sql record shows:
Empid AbsentDate
000838 2018-08-05
000838 2018-08-05
000838 2018-08-11
000838 2018-08-12
000838 2018-08-15
000838 2018-08-19
I have use two tables
1. tbl_admin_users- employee data stored
2. pmc_attendance- present records of employees
As mention in my query, I had removed p.emp_id IS NULL condition.
Due to this condition all your record which have p.punch_status is not null get filter out.
So you can try below query
SELECT m.emp_id AS `Empid`
, d.dt AS `AbsentDate`,
(CASE WHEN p.punch_status IS NULL
THEN 'A'
ELSE p.punch_status
END
) s
FROM ( SELECT DATE(t.added_date) AS dt
FROM pmc_attendance t
WHERE date(t.added_date) >= '2018-08-01'
AND date(t.added_date) < DATE_ADD( '2018-08-31' ,INTERVAL 1 DAY)
GROUP BY DATE(t.added_date)
ORDER BY DATE(t.added_date)
) d
CROSS
JOIN tbl_admin_users m
LEFT
JOIN pmc_attendance p
ON date(p.added_date) >= d.dt
AND date(p.added_date) < d.dt + INTERVAL 1 DAY
AND p.emp_id = m.emp_id
WHERE m.emp_id='000838' group by d.dt
ORDER
BY m.emp_id
, d.dt

How to select same column of a table twice as two different columns seperated date wise

i have the following mysql query , but its taking approx 5 minutes to execute, how can i decrease its execution time
select
revenue_center_group.description as rc_group,
revenue_center.description as revenue_center,
count(ytd.members) as total_ytd_members,
count(lytd.members) as total_lytd_members
from revenue_center
left join revenue_center_group on revenue_center_group.id = revenue_center.revenue_center_group_id
left join (
select membership.id as members,
membership.rc_id as rc_id
from membership
where membership.status =1
and DATE(membership.join_date)>= (SELECT DATE_FORMAT((SELECT DATE_FORMAT(date(now()) - INTERVAL 1 MONTH, '%Y-%m-%d')) ,'%Y-01-01 00:00:00'))
and DATE(membership.join_date)<= (SELECT DATE_FORMAT(LAST_DAY(date(now()) - INTERVAL 1 MONTH), '%Y-%m-%d 23:59:59'))ytd on revenue_center.id = ytd.rc_id
left join (
select
membership.id as members,
membership.rc_id as rc_id
from membership
where membership.status =1
and DATE(membership.join_date)>= (SELECT DATE_FORMAT((SELECT DATE_FORMAT((SELECT DATE_FORMAT(date(now()) - INTERVAL 1 MONTH, '%Y-%m-%d'))
- INTERVAL 1 YEAR, '%Y-%m-%d')) ,'%Y-01-01 00:00:00'))
and DATE(membership.join_date)<= (SELECT DATE_FORMAT((select DATE_FORMAT(LAST_DAY(date(now()) - INTERVAL 1 MONTH), '%Y-%m-%d')
- INTERVAL 1 YEAR),'%Y-%m-%d 23:59:59'))lytd on revenue_center.id = lytd.rc_id
group by revenue_center_group.description,revenue_center.description with rollup;

how to join tables and get sum of first table if second has multiple occurences

I have two tables "temp_user_batches" and "user_activities" i am trying to find sum of user_activities for users present in temp_user_batches table.
problem is sum of user_activities is getting multiplied by number of times in ratio of occurences of user in temp_user_batches table.
Below is temp_user_batches table
This is user_activities table
it is supposed to give sum of time_spent column 649 + 364 = 1013 but instead its giving 2016
my query is:
SELECT temp_user_batches.user_id as user_id,
temp_user_batches.activity_goal as goal,
DATE_SUB(CURDATE(), INTERVAL 7 day) as min_activity_date,
CURDATE() as max_activity_date,
(sum(user_activities.time_spent)/60) as total_time_spent
FROM temp_user_batches
INNER JOIN user_activities
ON temp_user_batches.user_id = user_activities.user_id
WHERE activity_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 day) AND CURDATE()
group by user_id, goal, max_activity_date, min_activity_date
You can use a derived table that contains the DISTINCT pairs of user_id, activity_goal from table temp_user_batches:
SELECT t1.user_id as user_id,
t2.activity_goal as goal,
DATE_SUB(CURDATE(), INTERVAL 7 day) as min_activity_date,
CURDATE() as max_activity_date,
(sum(t2.time_spent)/60) as total_time_spent
FROM (
SELECT DISTINCT user_id, activity_goal
FROM temp_user_batches) AS t1
INNER JOIN user_activities AS t2 ON t1.user_id = t2.user_id
WHERE activity_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 day) AND CURDATE()
group by user_id, goal, max_activity_date, min_activity_date
From my understanding, you should try to GROUP_BY the temp_user_batches on user_id, last_activity before joining it with user_activities. This is because now you join user_activities on 2 rows instead of 1 row the way you want (from what I understand).
Something like:
SELECT
temp_user_batches.user_id AS user_id,
temp_user_batches.activity_goal AS goal,
DATE_SUB(CURDATE(), INTERVAL 7 DAY) AS min_activity_date,
CURDATE() AS max_activity_date,
(SUM(user_activities.time_spent) / 60) AS total_time_spent
FROM
(SELECT
*
FROM
temp_user_batches
GROUP BY user_id , last_activity)
INNER JOIN
user_activities ON temp_user_batches.user_id = user_activities.user_id
WHERE
activity_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE()
GROUP BY user_id , goal , max_activity_date , min_activity_date

Query error in WHERE clause

SELECT product_key.contact_email, product_key.client_name, product_key.status, product_key.key, payment.paymentdate, product_key.id, MAX(paymentdate) AS latest_payment, DATE_ADD(MAX(paymentdate), INTERVAL 1 MONTH) AS expiration_date
FROM product_key LEFT OUTER JOIN payment ON payment.keyid=product_key.id
WHERE product_key.status = 'purchased' AND expiration_date = DATE_ADD(NOW(), INTERVAL 10 DAY) GROUP BY product_key.id
ORDER BY client_name asc
This is my query. I know I can't use an alias in a WHERE Clause since WHERE is first read before the SELECT. But even if I use something like this:
SELECT product_key.client_name, DATE_ADD(MAX(paymentdate), INTERVAL 1 MONTH) AS expiration_date
FROM product_key LEFT OUTER JOIN payment ON payment.keyid=product_key.id
WHERE DATE_ADD(MAX(paymentdate), INTERVAL 1 MONTH) = DATE_ADD(NOW(), INTERVAL 10 DAY) AND product_key.status = 'purchased'
GROUP BY product_key.id
ORDER BY client_name asc
Still an error. Please help. Thanks.
Since you're using an aggregate MAX() you should put it HAVING clause instead of WHERE. Assuming that other than that your query is correct and functional you can rewrite it like this
SELECT product_key.client_name,
DATE_ADD(MAX(paymentdate), INTERVAL 1 MONTH) AS expiration_date
FROM product_key LEFT OUTER JOIN payment
ON payment.keyid=product_key.id
AND product_key.status = 'purchased'
GROUP BY product_key.id
HAVING DATE_ADD(MAX(paymentdate), INTERVAL 1 MONTH) = DATE_ADD(NOW(), INTERVAL 10 DAY)
ORDER BY client_name
or
SELECT product_key.client_name,
DATE_ADD(MAX(paymentdate), INTERVAL 1 MONTH) AS expiration_date
FROM product_key LEFT OUTER JOIN payment
ON payment.keyid=product_key.id
AND product_key.status = 'purchased'
GROUP BY product_key.id
HAVING expiration_date = DATE_ADD(NOW(), INTERVAL 10 DAY)
ORDER BY client_name
You cannot use an alias defined in the select clause in a where clause. But that is ok, because you want to use having clause:
SELECT pk.contact_email, pk.client_name, pk.status, pk.key, p.paymentdate, pk.id,
MAX(paymentdate) AS latest_payment,
DATE_ADD(MAX(paymentdate), INTERVAL 1 MONTH) AS expiration_date
FROM product_key pk LEFT OUTER JOIN
payment p
ON p.keyid = pk.id
WHERE pk.status = 'purchased'
GROUP BY pk.id
HAVING expiration_date = DATE_ADD(NOW(), INTERVAL 10 DAY)
ORDER BY client_name asc;
You can use the alias in the having clause. Also, I added table aliases to your query to make it more readable.

SQL NOT IN Query

Can anyone help me with this MySQL query?
SELECT p.ProductID,
p.StoreID,
p.DiscountPercentage
FROM Products p
WHERE p.IsSpecial = 1
AND p.SpecialDate >= date_sub(now(),interval 15 minute)
AND p.DiscountPercentage >= ?DiscountPercentage
AND p.ProductID NOT IN (SELECT lf.LiveFeedID
From LiveFeed lf
WHERE p.ProductID = lf.ProductID
AND lf.DateAdded >= date_sub(now(),interval 30 day))
AND p.StoreID NOT IN (SELECT lf.LiveFeedID
From LiveFeed lf
WHERE p.StoreID = lf.StoreID
AND lf.DateAdded >= date_sub(now(),interval 6 hour))
ORDER BY p.StoreID, p.DiscountPercentage DESC
I'm trying join where the ProductID is not in the livefeed table in the last 30 days and where the storeid is not in the livefeed table in the last 6 hours, but it does not seem to be working. Any idea what I'm doing wrong?
At a glance, it would appear that your first subquery should be selecting ProductID, not LiveFeedID and your second subquery should be selecting StoreID not LiveFeedID
I'm too late:
SELECT p.ProductID,
p.StoreID,
p.DiscountPercentage
FROM Products p
WHERE p.IsSpecial = 1
AND p.SpecialDate >= date_sub(now(),interval 15 minute)
AND p.DiscountPercentage >= ?DiscountPercentage
AND p.ProductID NOT IN (SELECT lf.productid
FROM LIVEFEED lf
WHERE lf.DateAdded >= DATE_SUB(NOW(), INTERVAL 30 DAY))
AND p.storeid NOT IN (SELECT lf.storeid
FROM LIVEFEED lf
WHERE lf.DateAdded >= DATE_SUB(NOW(), INTERVAL 6 HOUR))
ORDER BY p.StoreID, p.DiscountPercentage DESC
You were using EXISTS syntax with a correllated subquery...
I'm trying to get the top discount for each store.
In that case, use:
SELECT p.StoreID,
MAX(p.DiscountPercentage)
FROM Products p
WHERE p.IsSpecial = 1
AND p.SpecialDate >= date_sub(now(),interval 15 minute)
AND p.DiscountPercentage >= ?DiscountPercentage
AND p.ProductID NOT IN (SELECT lf.productid
FROM LIVEFEED lf
WHERE lf.DateAdded >= DATE_SUB(NOW(), INTERVAL 30 DAY))
AND p.storeid NOT IN (SELECT lf.storeid
FROM LIVEFEED lf
WHERE lf.DateAdded >= DATE_SUB(NOW(), INTERVAL 6 HOUR))
GROUP BY p.storeid
ORDER BY p.StoreID, p.DiscountPercentage DESC