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
Related
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
I need to get all the Paid and Provisional Entry from the last 7 days but I keep getting everything returned. I am unsure what I am doing wrong I have read through quite a few posts on here and cant fathom what its. MySQL 5.6 if it makes any diffrence to what I have been doing.
SELECT
DATE_FORMAT(FROM_UNIXTIME(ct.entry_date),'%d/%m/%Y') AS booking_date,
cd.field_id_69 AS marriage_date,
cd.field_id_54 AS email_address,
CONCAT(cd.field_id_9, ' ', cd.field_id_10) AS bride_name,
CONCAT(cd.field_id_13, ' ', cd.field_id_14) AS groom_name,
ctco.title AS centre_and_course_date,
(SELECT DATE_FORMAT(FROM_UNIXTIME(col_id_1),'%d/%m/%Y') FROM
exp_channel_grid_field_50 cg WHERE cg.entry_id = ctco.entry_id ORDER BY
cg.row_id DESC LIMIT 1) AS course_end_date,
ct.status AS payment_status
FROM exp_channel_titles ct
JOIN exp_channel_data cd ON cd.entry_id = ct.entry_id
JOIN exp_relationships rco ON rco.parent_id = ct.entry_id AND rco.field_id = 41
JOIN exp_channel_titles ctco ON rco.child_id = ctco.entry_id
WHERE ct.channel_id = 2
AND ct.entry_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY)
AND ct.status = 'Paid'
AND ct.status = 'Provisional';
There is problem in your WHERE statement
AND ct.entry_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND ct.status = 'Paid' AND ct.status = 'Provisional';
The BETWEEN keyword needs to be followed by 2 dates, so ct.status = 'Paid' will be converted to DATE which return NULL. Hence your WHERE statement turns into.
AND ct.entry_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND NULL AND ct.status = 'Provisional';
The result is that your query will return all data that have status = 'Provisional'.
You could try to modify the WHERE statement to
AND ct.entry_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE() AND ct.status IN ('Paid', 'Provisional');
The syntax of BETWEEN is BETWEEN startdate AND enddate. You wrote:
ct.entry_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND ct.status = 'Paid'
So it's using DATE_SUB(CURDATE(), INTERVAL 7 DAY) as the starting date, and ct.status = 'Paid' as the ending date. I'm surprised it's matching anything.
Change it to:
ct.entry_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE()
Or if you don't have any dates in the future, you can simply write:
ct.entry_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
I would like your help with the following:
query 1:
SELECT stock.ST_CODE as xCODE, (sum(ordercont.QTY) / 12) as x12WeeksAvg
FROM orders
LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
LEFT JOIN stock ON stock.PD_CODE = ordercont.PD_CODE
WHERE stock.ST_CODE IS NOT NULL
AND orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 84 DAY)
AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
GROUP BY stock.ST_CODE
query 2:
SELECT stock.ST_CODE as xCODE, (sum(ordercont.QTY) / 4) as x4WeeksAvg
FROM orders LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
LEFT JOIN stock ON stock.PD_CODE = ordercont.PD_CODE
WHERE stock.ST_CODE IS NOT NULL
AND orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 28 DAY)
AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
GROUP BY stock.ST_CODE
Is there any way to have the result like this (the queries returns different number of results):
------------------------------------
| xCode | x12WeeksAvg | x4WeeksAvg |
------------------------------------
| ... | ... | ... |
------------------------------------
Thank you!!
Split the BETWEEN condition
orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 84 DAY)
AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
into two parts
AND orders.O_CUSTDATE >= DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 84 DAY)
AND orders.O_CUSTDATE <= DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
and rewrite it to
AND orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 84) DAY
AND orders.O_CUSTDATE <= CURDATE() - INTERVAL (DAYOFWEEK(NOW()) - 1) DAY
to get shorter and more readable code. Do the same for the second query.
Now the two queries differ only in two expressions
(sum(ordercont.QTY) / 12) as x12WeeksAvg
(sum(ordercont.QTY) / 4) as x4WeeksAvg
orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 84) DAY
orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 28) DAY
Given
<X>: orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 84) DAY
and
<Y>: orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 28) DAY
you can use conditional aggregation to combine the two queries:
SELECT stock.ST_CODE as xCODE,
(sum(CASE WHEN <X> THEN ordercont.QTY ELSE 0 END) / 12) as x12WeeksAvg,
(sum(CASE WHEN <Y> THEN ordercont.QTY ELSE 0 END) / 4) as x4WeeksAvg
FROM orders
LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
LEFT JOIN stock ON stock.PD_CODE = ordercont.PD_CODE
WHERE stock.ST_CODE IS NOT NULL
AND orders.O_CUSTDATE <= CURDATE() - INTERVAL (DAYOFWEEK(NOW()) - 1) DAY
GROUP BY stock.ST_CODE
Replace <X> and <Y> accordingly.
Update
To improve the performance you can add
AND orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 84) DAY
to the WHERE clause.
Also note that the condition stock.ST_CODE IS NOT NULL will convert your LEFT JOINs to INNER JOINs. So you could as well just write JOIN.
You can subquery them like this to get your desired output:
SELECT A.xCODE,
COALESCE(B.x12WeeksAvg, 'N/A') as x12WeeksAvg,
COALESCE(C.x4WeeksAvg, 'N/A') as x4WeeksAvg
FROM (SELECT DISTINCT ST_CODE as xCODE FROM stock) A
LEFT JOIN (
SELECT stock.ST_CODE as xCODE, (sum(ordercont.QTY) / 12) as x12WeeksAvg
FROM orders
LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
LEFT JOIN stock ON stock.PD_CODE = ordercont.PD_CODE
WHERE stock.ST_CODE IS NOT NULL
AND orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 84 DAY) AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
GROUP BY stock.ST_CODE
) B ON A.xCODE = B.xCODE
LEFT JOIN (
SELECT stock.ST_CODE as xCODE, (sum(ordercont.QTY) / 4) as x4WeeksAvg
FROM orders
LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
LEFT JOIN stock ON stock.PD_CODE = ordercont.PD_CODE
WHERE stock.ST_CODE IS NOT NULL
AND orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 28 DAY) AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
GROUP BY stock.ST_CODE
) C ON A.xCODE = C.xCODE
WHERE COALESCE(B.x12WeeksAvg, C.x4WeeksAvg) IS NOT NULL
This query returned 385 strings
SELECT order_number
FROM `order`
inner join order_delivery_data on `order`.order_id = order_delivery_data.order_id
where order_status = 'delivered' AND order_statusUpdatedAt >= DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)
and order_delivery_data_name in ('London')
this returned 74 strings
SELECT order_number
FROM `order`
inner join order_delivery_data on `order`.order_id = order_delivery_data.order_id
where order_status = 'delivered' AND order_statusUpdatedAt BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 10 DAY)
AND DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)
and order_delivery_data_name in ('London')
How join it, that in that there are two columns
try this:
SELECT t1.order_number as order_t1, t2.order_number as order_t2 FROM
( SELECT order_number,`order`.order_id
FROM `order`
inner join order_delivery_data on `order`.order_id = order_delivery_data.order_id
where order_status = 'delivered' AND order_statusUpdatedAt BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 10 DAY)
AND DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)
and order_delivery_data_name in ('London')
) as t1
LEFT JOIN
(SELECT order_number,`order`.order_id
FROM `order`
inner join order_delivery_data on `order`.order_id = order_delivery_data.order_id
where order_status = 'delivered' AND order_statusUpdatedAt BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 10 DAY)
AND DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)
and order_delivery_data_name in ('London')
) as t2
ON t1.order_id = t2.order_id
UNION ALL
SELECT t1.order_number as order_t1, t2.order_number as order_t2 FROM
( SELECT order_number,`order`.order_id
FROM `order`
inner join order_delivery_data on `order`.order_id = order_delivery_data.order_id
where order_status = 'delivered' AND order_statusUpdatedAt BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 10 DAY)
AND DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)
and order_delivery_data_name in ('London')
) as t1
RIGHT JOIN
(SELECT order_number,`order`.order_id
FROM `order`
inner join order_delivery_data on `order`.order_id = order_delivery_data.order_id
where order_status = 'delivered' AND order_statusUpdatedAt BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 10 DAY)
AND DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)
and order_delivery_data_name in ('London')
) as t2
ON t1.order_id = t2.order_id;
You need to use FULL JOIN, i.e. UNION ALL when using mysql:
first_query UNION ALL second_query
I would like to combine different results from the same table as one big result.
SELECT host_name,stats_avgcpu,stats_avgmem,stats_avgswap,stats_avgiowait
FROM sar_stats,sar_hosts,sar_appgroups,sar_environments
WHERE stats_host = host_id
AND host_environment = env_id
AND env_name = 'Staging 2'
AND host_appgroup = group_id
AND group_name = 'Pervasive'
AND DATE(stats_report_time) = DATE_SUB(curdate(), INTERVAL 1 DAY)
SELECT AVG(stats_avgcpu),AVG(stats_avgmem),AVG(stats_avgswap),AVG(stats_avgiowait)
FROM sar_stats
WHERE stats_id = "stat_id of the first query" and DATE(stats_report_time)
BETWEEN DATE_SUB(curdate(), INTERVAL 8 DAY) and DATE_SUB(curdate(), INTERVAL 1 DAY)
SELECT AVG(stats_avgcpu),AVG(stats_avgmem),AVG(stats_avgswap),AVG(stats_avgiowait)
FROM sar_stats
WHERE stats_id = "stat_id of the first query" and DATE(stats_report_time)
BETWEEN DATE_SUB(curdate(), INTERVAL 31 DAY) and DATE_SUB(curdate(), INTERVAL 1 DAY)
Desired output would be something like ...
host_name|stats_avgcpu|stats_avgmem|stats_avgswap|stats_avgiowait|7daycpuavg|7daymemavg|7dayswapavg|7dayiowaitavg|30daycpuavg|30daymemavg|....etc
SQL Fiddle
http://sqlfiddle.com/#!8/4930b/3
It seems like this is what you want. I updated the first query to use proper ANSI JOIN syntax and then for the additional two queries they were joined via a LEFT JOIN on the stats_host field:
SELECT s.stats_host,
h.host_name,
s.stats_avgcpu,
s.stats_avgmem,
s.stats_avgswap,
s.stats_avgiowait,
s7.7dayavgcpu,
s7.7dayavgmem,
s7.7dayavgswap,
s7.7dayavgiowait,
s30.30dayavgcpu,
s30.30dayavgmem,
s30.30dayavgswap,
s30.30dayavgiowait
FROM sar_stats s
INNER JOIN sar_hosts h
on s.stats_host = h.host_id
INNER JOIN sar_appgroups a
on h.host_appgroup = a.group_id
and a.group_name = 'Pervasive'
INNER JOIN sar_environments e
on h.host_environment = e.env_id
and e.env_name = 'Staging 2'
LEFT JOIN
(
SELECT s.stats_host,
AVG(s.stats_avgcpu) AS '7dayavgcpu',
AVG(s.stats_avgmem) AS '7dayavgmem',
AVG(s.stats_avgswap) AS '7dayavgswap',
AVG(s.stats_avgiowait) AS '7dayavgiowait'
FROM sar_stats s
WHERE DATE(stats_report_time) BETWEEN DATE_SUB(curdate(), INTERVAL 8 DAY) AND DATE_SUB(curdate(), INTERVAL 1 DAY)
GROUP BY s.stats_host
) s7
on s.stats_host = s7.stats_host
LEFT JOIN
(
SELECT s.stats_host,
AVG(s.stats_avgcpu) AS '30dayavgcpu',
AVG(s.stats_avgmem) AS '30dayavgmem',
AVG(s.stats_avgswap) AS '30dayavgswap',
AVG(s.stats_avgiowait) AS '30dayavgiowait'
FROM sar_stats s
WHERE DATE(s.stats_report_time) BETWEEN DATE_SUB(curdate(), INTERVAL 31 DAY) AND DATE_SUB(curdate(), INTERVAL 1 DAY)
GROUP BY s.stats_host
) s30
on s.stats_host = s30.stats_host
WHERE DATE(s.stats_report_time) = DATE_SUB(curdate(), INTERVAL 1 DAY);
see SQL Fiddle with Demo