How to consolidate 3 SQL-queries in one - mysql

I have three separate queries and need to combine it in one to prepare data for a chart. So the common parameter for all 3 datasets is the date.
Please help me to do it.
1)
SELECT COUNT(id) Registrations, regdate
FROM wpu_users
WHERE regdate >= '2020-01-09'
GROUP BY regdate;
2)
SELECT ROUND(SUM(total)) as amount, DATE(datetime) as date
FROM wp_payments
WHERE site_id=4 AND status=1
GROUP BY date
ORDER BY date DESC
3)
SELECT ROUND(SUM(cnt)) as Matrix, DATE(datetime) as date
FROM wp_payments
WHERE site_id=4
AND status=1
AND currency='USD'
AND description LIKE '% + %'
AND datetime IS NOT NULL
GROUP BY date
The result should be a table with columns:
Registrations
amount
Matrix
date

Based on your requirement. try this
SELECT
tab1.Registrations as "Registrations",
tab2.amount as "Amount",
tab3.Matrix as "Matrix",
tab1.regdate as "Date"
FROM
( SELECT COUNT( id ) Registrations, regdate FROM wpu_users where regdate >= '2020-01-09' GROUP BY regdate ) tab1
INNER JOIN (
SELECT
ROUND( SUM( total ) ) AS amount,
DATE( datetime ) AS date
FROM
wp_payments
WHERE
site_id = 4
AND STATUS = 1
GROUP BY
date
) tab2 ON tab1.regdate = tab2.date
INNER JOIN (
SELECT
ROUND( SUM( cnt ) ) AS Matrix,
DATE( datetime ) AS date
FROM
wp_payments
WHERE
site_id = 4
AND STATUS = 1
AND currency = 'USD'
AND description LIKE '% + %'
AND datetime IS NOT NULL
GROUP BY
date
) tab3 ON tab1.regdate = tab3.date

Related

SELECT the first date in which 3 consecutive entries are between two dates

I would like to know the first date of the first 3 consecutive entries that are between two dates. Based on my SQLFiddle, I would expect the output to be '2021-01-24'.
I've looked at many examples but can't get them to work.
This query is not working how I want it to, I can't figure out the missing piece of my query. Here is the SQLFIDDLE: http://sqlfiddle.com/#!9/935fbd/1
SELECT DISTINCT
logDate
FROM
FoodLog
WHERE
studentID = '1329' AND logDate BETWEEN '2021-01-01' AND '2021-05-01'
GROUP BY
logDate
HAVING
COUNT(logDate) = 3
I've tried working with the following, but can't figure out how to limit the search to studentID='1329' or my date range:
SELECT DISTINCT
f.id,
f.logDate
FROM
FoodLog f,
(
SELECT
f1.logDate START,
f2.logDate NEXT
FROM
FoodLog f1,
FoodLog f2
WHERE
f2.logDate <= DATE_ADD(f1.logDate, INTERVAL 1 DAY) AND f2.logDate > f1.logDate
) f2
WHERE
f.logDate = f2.start OR(
f.logDate = f2.next AND f2.start IS NOT NULL
)
LIMIT 1
WITH
cte1 AS (
SELECT DISTINCT logDate
FROM FoodLog
WHERE logDate BETWEEN '2021-01-01' AND '2021-05-01'),
cte2 AS (
SELECT logDate, LEAD(logDate, 2) OVER (ORDER BY logDate) next2date
FROM cte1
)
SELECT MIN(logDate) logDate
FROM cte2
WHERE DATEDIFF(next2date, logDate) = 2;
fiddle

Need help in executing SQL query

Here are two queries with results, I need to run one query to get same result.
1-Total slots
2-created Date
3-start date
4-end date
5-Unused Slots
First Query:-
SELECT COUNT( id ) as total_slots ,
created_date, MIN( DATE ) as start_date ,
MAX( DATE ) as end_date
FROM slots
GROUP BY created_date;
Query 1(Result)
Here is image with query result
Can I get unused slots in same query as I am getting from below query?
But here
SELECT COUNT( id ) AS unused
FROM slots
WHERE user_id =0
AND created_date = '2016-10-01 20:20:20'
Result Query with created date 2016-10-01 20:20:20
unused
79
SELECT COUNT( id ) AS unused
FROM slots
WHERE user_id =0
AND created_date = '2016-10-01 20:24:45'
Result Query with created date 2016-10-01 20:24:45
unused
51
Try
SELECT
COUNT( id ) as total_slots,
created_date,
MIN( DATE ) as start_date,
MAX( DATE ) as end_date,
COUNT(CASE WHEN user_id = 0 THEN 1 END) as unused_slots
FROM slots
GROUP BY created_date;

Get the most popular product per day, MySQL for Magento

I need to get a table that contains the most popular product sold per day. All data is stored in Magento, and I use MySQL to write the query. The only table I need is Sales_flat_order_item table.
The final table should have 3 columns: Date, Product SKU, and number of units sold of the most popular product that day - MaxQty.
I came up with the query that works for me, but I would like to know how it can be improved since I use the same subquery twice in my code:
1 Select Date, Product Id, Sku, and Quantity from sales_flat_order_item - Subquery1
2 Select Date and Maximum Quantity from Subquery1 - Subquery2
3 Join them together knowing that dates should be the same, and Quantity from Subquery1 should be equal to Maximum Quantity from Subquery2
SELECT DATE( sq2.created_at ) AS CreatedAt, sq0.sku AS SKU, sq2.MaxQty
FROM (
SELECT created_at, product_id, sku, SUM( qty_ordered ) AS qty
FROM `sales_flat_order_item`
GROUP BY DATE( created_at ) , product_id
) AS sq0
JOIN (
SELECT sq.created_at, MAX( sq.qty ) AS MaxQty
FROM (
SELECT created_at, product_id, SUM( qty_ordered ) AS qty
FROM `sales_flat_order_item`
GROUP BY DATE( created_at ) , product_id
) AS sq
GROUP BY DATE( sq.created_at )
) AS sq2 ON DATE( sq2.created_at ) = DATE( sq0.created_at )
AND sq2.MaxQty = sq0.qty
GROUP BY DATE( CreatedAt )
I believe this should do what you want.
I added a WHERE clause to run it only for this month, in case you have a huge database so it should not take much time.
SELECT day, sku, MAX(qty_total) AS qty FROM (
SELECT DATE(created_at) AS day, sku, SUM(qty_ordered) AS qty_total
FROM `sales_flat_order_item`
WHERE created_at > '2015-07%'
GROUP BY sku, day
ORDER BY qty_total DESC
) AS item_count
GROUP BY day

Get the 0 value if No result in column -- MySQL

I have the following query
SELECT COUNT( iContactId ) AS Users, DATE( dCreatedAt ) AS ActivityDate
FROM contacts WHERE iAppId =".$iAppId."
AND DATE(dCreatedAt) IN (CURRENT_DATE(), CURRENT_DATE()-1 )
GROUP BY ActivityDate
by this i am getting
Users |ActivityDate
1 |2014-09-19
i want 0 if there is no match rows
e.g
Users |ActivityDate
0 |CURRENT_DATE()
0 | CURRENT_DATE()-1
How can i do that.
QUERY
SELECT
COUNT(C.iContactId) AS Users,
DATE(C.dCreatedAt) AS ActivityDate
FROM
contacts C
LEFT OUTER JOIN
(
SELECT CURRENT_DATE() AS Dates FROM dual
UNION
SELECT CURRENT_DATE() - 1 AS Dates FROM dual
) D
ON
D.Dates = DATE(C.dCreatedAt)
WHERE
C.iAppId =".$iAppId."
GROUP BY
C.ActivityDate
You could use union
SELECT COUNT( iContactId ) AS Users, CURRENT_DATE() AS ActivityDate
FROM contacts WHERE iAppId =".$iAppId."
AND DATE(dCreatedAt) = CURRENT_DATE()
UNION
SELECT COUNT( iContactId ) AS Users, CURRENT_DATE() - 1 AS ActivityDate
FROM contacts WHERE iAppId =".$iAppId."
AND DATE(dCreatedAt) = CURRENT_DATE() - 1
QUERY
SELECT
ISNULL( iContactId ,0) AS Users,
DATE( dCreatedAt ) AS ActivityDate
FROM contacts
WHERE iAppId =".$iAppId."
AND DATE(dCreatedAt) IN (CURRENT_DATE(), CURRENT_DATE()-1 )
GROUP BY ActivityDate
In most answers this is used voor date substraction:
SELECT CURRENT_DATE() - 1
-> 20140919
This will result in impliciet type casting and date wil be casted to int, use this instead:
SELECT CURRENT_DATE - INTERVAL 1 DAY
-> 2014-09-19
My solution
SELECT
d.ActivityDate,
COUNT(c.iContactId) Users
FROM
(
SELECT CURRENT_DATE - INTERVAL 1 DAY ActivityDate FROM DUAL
UNION
SELECT CURRENT_DATE FROM DUAL
) d
LEFT JOIN
contacts c
ON DATE(c.dCreatedAt) = d.ActivityDate
AND c.iAppId = " . $iAppId . "
GROUP BY d.ActivityDate

initialise all values in a query to 0 and top to NULL if there's no result

Hi all i execute this query to get a table where there's statistics of some database information.. i'd like to intialise the fields that don't exist ( because the query is executed in different dates and sometimes there's a day where there's nothing ) so i'd like it to return 0 and NULL ( in TOP column )
SELECT
SUM(IF(`TOP` = 'one',`Nb`,0)) as first_one,
SUM(IF(`TOP` = 'two',`Nb`,0)) as second_one,
SUM(IF(`TOP` = 'three',`Nb`,0)) as thrid_one,
SUM(IF(`TOP` NOT IN ('three','two','one'),`Nb`,0)) as forth_one,
GROUP_CONCAT(IF(`TOP` NOT IN ('three','two','one'),`TOP`,'') SEPARATOR '') as `OR`
FROM (
SELECT
COUNT(*) as Nb,
'one' as `TOP`
FROM
mytable
WHERE
TYPE = 'MSS'
AND YEAR(date) = YEAR(CURDATE())
AND MONTH(date) = MONTH(CURDATE())
UNION ALL
SELECT
COUNT(*) as Nb,
'two' as `TOP`
FROM
mytable
WHERE
TYPE = 'MSS'
AND S=0
AND YEAR(date) = YEAR(CURDATE())
AND MONTH(date) = MONTH(CURDATE())
UNION ALL
SELECT
COUNT(*) as Nb,
'three' as `TOP`
FROM
mytable
WHERE
TYPE = 'MSS'
AND S<>0
AND YEAR(date) = YEAR(CURDATE())
AND MONTH(date) = MONTH(CURDATE())
UNION ALL
SELECT
`Nb`,
`TOP`
FROM(
SELECT
COUNT(*) as Nb ,
`OR` as `TOP`
FROM
mytable
WHERE
TYPE = 'MSS'
AND YEAR(date) = YEAR(CURDATE())
AND MONTH(date) = MONTH(CURDATE())
GROUP BY
`OR`
ORDER BY
Nb DESC
LIMIT 1
) as tmp
)as tmp1
Assuming that in tmp1 you have data you need but with "gaps" (days when there were no data at all) you could RIGHT JOIN tmp1 to table tmp2 using day (I assume that you have such column in tmp1 table). So tmp2 would be just list of days:
SELECT '2013-05-17' as day UNION SELECT '2013-05-18' UNION SELECT ...
I could elaborate my answer if you'd like to provide your DB schema.
You can replace each subquery with:
SELECT
IFNULL(tmp.Nb,0) as Nb,
IFNULL(tmp.`TOP`, 'value') as `TOP`
FROM (
--subquery
) as tmp
Example for the first subquery:
SELECT
IFNULL(tmp.Nb,0) as Nb,
IFNULL(tmp.`TOP`, 'one') as `TOP`
FROM (
SELECT
COUNT(*) as Nb,
'one' as `TOP`
FROM
mytable
WHERE
TYPE = 'MSS'
AND YEAR(date) = YEAR(CURDATE())
AND MONTH(date) = MONTH(CURDATE())
) as tmp
SQL is good at grouping existing entities into categories, but bad at "creating" entities itself. I would advise either a generic number table (really just the numbers from 0 to a few hundredthousand) if you have also non-date categories or as Wiktor suggested a date-Table which gets filled every now and then and has the next few years as well as the time since your program is working.
With a date table
list_dates (
id int(11) not null primary key auto_increment,
dateval date not null
)
you could start your queries from that table (with a reasonable range, of course) and count every thing else:
select list_dates.dateval as date, count(*) as cnt
from list_dates
left join actions on actions.actiontime >= (cast list_dates.date_val as datetime)
and actions.actiontime < (cast list_dates.date_val `interval 1 day as datetime)
where list_dates.dateval between '$fromDate' and '$toDate'
group by list_dates.dateval
;
or starting with a number table numbers
select $fromDate + interval numbers.number day as date, count(*) as cnt
from numbers
left join actions
on actions.actiontime >= (cast $fromDate + interval numbers.number day as datetime)
and actions.actiontime < (cast $fromDate + interval (1 + numbers.number) day as datetime)
where numbers.number >= 0 and numbers.number < $countDates
group by numbers.number
;
One Day
If you really want just that one day (today) then you can of course use a anonymous subselect- Table instead, so it becomes
select list_dates.dateval as date, count(*) as cnt
from ( select curdate() as dateval ) as list_dates
left join actions on actions.actiontime >= (cast list_dates.date_val as datetime)
and actions.actiontime < (cast list_dates.date_val `interval 1 day as datetime)
where list_dates.dateval between '$fromDate' and '$toDate'
group by list_dates.dateval
;