Select 2 Column with Different Conditions - mysql

I need to create a query that give me completed and unpaid transaction in 2019 grouped weekly. I already create the query to generate the completed transaction, but I stuck when try to combine the unpaid transaction query into the completed transaction query
This is the query for completed transaction
SELECT WEEK(A.plat_create_time, 1) AS 'Week Create Time',
COUNT(t1.lp_sign_time) AS 'Completed Order'
FROM deli_order A
LEFT JOIN
(
SELECT order_code, code, lp_sign_time
FROM pg_send_package
UNION
SELECT D.order_code, D.oms_code, C.cm_sign_time
FROM pg_package C
INNER JOIN pg_order D ON C.pg_order_id = D.id
) t1 ON t1.order_code = A.order_code
AND t1.code = A.code
AND YEAR(A.plat_create_time) = 2019
WHERE (YEAR(A.plat_create_time) = 2019) AND A.status = 6 AND t1.lp_sign_time IS NOT NULL
GROUP BY WEEK(A.plat_create_time, 1);
And its generate something like this
Week | Completed Order
1 886
2 734
3 868
4 1000
And this is the query that I already try to generate both completed and unpaid transaction
SELECT WEEK(A.plat_create_time, 1) AS 'Week Create Time',
COUNT(t1.lp_sign_time) AS 'Completed Order',
COUNT(t2.plat_create_time) AS 'Unpaid Order'
FROM deli_order A
LEFT JOIN
(
SELECT order_code, code, lp_sign_time
FROM pg_send_package
UNION
SELECT D.order_code, D.oms_code, C.cm_sign_time
FROM pg_package C
INNER JOIN pg_order D ON C.pg_order_id = D.id
) t1 ON t1.order_code = A.order_code
AND t1.code = A.code
AND YEAR(A.plat_create_time) = 2019
LEFT JOIN
(
SELECT order_code, WEEK(plat_create_time,1) AS 'Create Time'
FROM deli_order
WHERE pay_state = 0 AND (YEAR(plat_create_time) = 2019)
) t2 ON t2.order_code = A.order_code
WHERE (YEAR(A.plat_create_time) = 2019) AND A.status = 6 AND t1.lp_sign_time IS NOT NULL
GROUP BY WEEK(A.plat_create_time, 1);
but when I execute it, MySQL always give error message 'Unknown column 't2.plat_create_time' in field list'. My expected result is something like this
Week | Completed Order | Unpaid Order
1 886 51
2 734 42
3 868 40
4 1000 31
What should I change in my query?

Change:
SELECT order_code, WEEK(plat_create_time,1) AS 'Create Time'
to:
SELECT order_code, WEEK(plat_create_time,1) AS 'Create Time', plat_create_time

Related

Why not equal displaying actual result in select queries by joining two select tables

I am using MySQL. I am trying to join two queries by != condition. For this example it should return empty result set. But it seems the condition is not applied. Why is this so?
My attempts are below:
SELECT today_student.* FROM (
SELECT scd.student_id, sc.transaction_date
FROM student_collection_details scd
INNER JOIN student_collection sc
ON (scd.student_collection_id = sc.id)
WHERE 1=1
AND sc.transaction_date BETWEEN DATE('2022-06-01 00:00:00') AND DATE('2022-06-27 00:00:00')
AND scd.admission_year_id = 2
AND scd.month_id = 21
AND scd.collection_head_id = 9
GROUP BY scd.student_id
) prev_student,
(
SELECT scd.student_id, sc.transaction_date
FROM student_collection_details scd
INNER JOIN student_collection sc
ON (scd.student_collection_id = sc.id)
WHERE 1=1
AND sc.transaction_date = DATE('2022-06-28 00:00:00')
AND scd.admission_year_id = 2
AND scd.month_id = 21
AND scd.collection_head_id = 9
GROUP BY scd.student_id
) today_student
WHERE 1=1
AND prev_student.student_id != today_student.student_id
prev_student returns:
1196; 2022-06-20 00:00:00
1861; 2022-06-18 00:00:00
today_student returns:
1196; 2022-06-28 00:00:00
1861; 2022-06-28 00:00:00
Use a HAVING clause with the condition that the min transaction_date is '2022-06-28':
SELECT scd.student_id,
MIN(sc.transaction_date) transaction_date
FROM student_collection_details scd INNER JOIN student_collection sc
ON scd.student_collection_id = sc.id
WHERE sc.transaction_date BETWEEN '2022-06-01 00:00:00' AND '2022-06-28 00:00:00'
AND scd.admission_year_id = 2
AND scd.month_id = 21
AND scd.collection_head_id = 9
GROUP BY scd.student_id
HAVING MIN(sc.transaction_date) = '2022-06-28 00:00:00';

Convert mySQL partition query to mySQL 5.7 Compatible query where there are two sums in one query

I have the following query that works perfectly in mysql 8:
SELECT
J.JobID, Month(WH.DateStart) as MonthCharged, Year(WH.DateStart) as YearCharged, sum(WH.Duration) as HoursWorkedInMonth, sum(WH.Duration) over (partition by J.JobID order by Month(WH.DateStart), Year(WH.DateStart)) as CumulativeJobHoursWorked
FROM
tblJob J
JOIN tblTask T ON CONCAT('JOB-', RIGHT(YEAR(J.DateCreated), 2), '-', LPAD(J.JobID, 4, '0')) = T.SourceID
LEFT JOIN xrefTasktoEmployee XT ON T.TaskID = XT.TaskID
LEFT JOIN tblWorkHistory WH ON XT.WorkHistoryID = WH.WorkHistoryID
LEFT JOIN tblRates R ON XT.rateID = R.RateID
Where WH.Duration is not NULL
Group by J.JobID, Month(WH.DateStart), Year(WH.DateStart)
And it produces the following results:
Job ID
Month Charged
Year Charged
HoursWorkedInMonth
CumulativeJobHoursWorked
1
3
2021
23.98
23.98
1
4
2021
24.98
47.96
2
3
2021
8
8
3
2
2021
8
8
4
3
2021
1
1
5
2
2021
10
10
Notice how I am summing the hours worked in the month & year for a particular job, then I need the cumulative for that Job for the year.
I can't seem to figure out how to do this in MySQL 5.7 by using variables. Does anyone have any insights?
Thanks
Here is what I finally got to work:
SELECT
J.JobID, Month(WH.DateStart) as MonthCharged, Year(WH.DateStart) as YearCharged, sum(WH.Duration) as HoursWorkedInMonth, (SELECT
sum(WH2.Duration)
FROM
tblJob J2
JOIN tblTask T2 ON CONCAT('JOB-', RIGHT(YEAR(J2.DateCreated), 2), '-', LPAD(J2.JobID, 4, '0')) = T2.SourceID
LEFT JOIN xrefTasktoEmployee XT2 ON T2.TaskID = XT2.TaskID
LEFT JOIN tblWorkHistory WH2 ON XT2.WorkHistoryID = WH2.WorkHistoryID
Where WH2.Duration is not NULL and J2.JobID = J.JobID and DATE_FORMAT(WH2.DateStart, '%m-%Y') <= DATE_FORMAT(WH.DateStart, '%m-%Y')) as CumulativeJobHoursWorked
FROM
tblJob J
JOIN tblTask T ON CONCAT('JOB-', RIGHT(YEAR(J.DateCreated), 2), '-', LPAD(J.JobID, 4, '0')) = T.SourceID
LEFT JOIN xrefTasktoEmployee XT ON T.TaskID = XT.TaskID
LEFT JOIN tblWorkHistory WH ON XT.WorkHistoryID = WH.WorkHistoryID
Where WH.Duration is not NULL
Group by J.JobID, Month(WH.DateStart), Year(WH.DateStart)

Need help in building MYSQL query to count two content from single row/table

I'm trying to get count of two set of data which is listed under same table name, with specific date range.
Table 'Event'
u_id event Create
123 F_log 25-Sep-16
127 C_log 25-Sep-16
123 F_log 25-Sep-16
126 F_log 25-Sep-16
185 M_log 25-Sep-16
146 D_log 25-Sep-16
173 F_log 26-Sep-16
183 C_log 26-Sep-16
193 F_log 26-Sep-16
204 M_log 27-Sep-16
214 D_log 27-Sep-16
225 F_log 27-Sep-16
Expected result
Created F_log C_log
25-Sep-16 2 1
26-Sep-16 2 1
My query which is not giving correct result;
SELECT COUNT (DISTINCT e.user_id) AS Flash,
COUNT (DISTINCT et.user_id) AS Client,
TO_CHAR (e.created) AS Date_created
FROM events e INNER JOIN events et ON e.user_id = et.user_id
WHERE e.created BETWEEN '25-SEP-15' AND '27-SEP-15'
AND e.event_type = 'Flash C log'
AND et.event_type = 'Client C log'
GROUP BY TO_CHAR (e.created);
Query
SELECT t.`Create`,
SUM(CASE WHEN t.`F_log` > 0 THEN 1 ELSE 0 END) as `F_log`,
SUM(CASE WHEN t.`C_log` > 0 THEN 1 ELSE 0 END) as `C_log` FROM(
select `u_id`, `Create`,
SUM(CASE WHEN `event` = 'F_log' THEN 1 ELSE 0 END) AS `F_log`,
SUM(CASE WHEN `event` = 'C_log' THEN 1 ELSE 0 END) AS `C_log`
FROM `Event`
GROUP BY `u_id`, `Create`
)t
GROUP BY t.`Create`;
The COUNTs has to be done in separate subqueries. This should work.
SELECT DISTINCT E.created,F.flash,C.client
FROM events E
LEFT JOIN (
SELECT created,COUNT(DISTINCT user_id) as flash
FROM events
WHERE event_type LIKE 'Flash C log'
GROUP BY created
) F
ON F.created = E.created
LEFT JOIN (
SELECT Created,COUNT(DISTINCT user_id) as client
FROM events
WHERE event_type LIKE 'Client C log'
GROUP BY created
) C
ON C.created = E.created
WHERE E.created BETWEEN '2016-09-25' AND '2016-09-27'
Fiddle with results
EDIT: As of your comments, I have made a question that adds a column of the distinct combined userids with clients and flash logs for each date. I added a little data to that fiddle to test.
SELECT DISTINCT E.created,F.flash,C.client,FC.combined
FROM events E
LEFT JOIN (
SELECT created,COUNT(DISTINCT user_id) as flash
FROM events
WHERE event_type LIKE 'Flash C log'
GROUP BY created
) F
ON F.created = E.created
LEFT JOIN (
SELECT Created,COUNT(DISTINCT user_id) as client
FROM events
WHERE event_type LIKE 'Client C log'
GROUP BY created
) C
ON C.created = E.created
LEFT JOIN (
SELECT Created,COUNT(DISTINCT user_id) as combined
FROM events
WHERE event_type LIKE 'Client C log' OR event_type LIKE 'Flash C log'
GROUP BY created
) FC
ON FC.created = E.created
WHERE E.created BETWEEN '2016-09-25' AND '2016-09-27'
SQL Fiddle for answer 2
select to_char(cast(created as date),'YYYY-MM-DD') as Report_date,
count(distinct(case when event_type in ('Flash C Log') then user_id else 0 end)) as Flash_Log,
count(distinct(case when (event_type = 'Client C Log') then user_id else 0 end)) as Client_Log
from events e
where created between '25-SEP-16' and '27-SEP-16'
group by to_char(cast(created as date),'YYYY-MM-DD')
order by to_char(cast(created as date),'YYYY-MM-DD');

MySQL query slow in Where MONTH(datetime)

I am trying to add index in datetime, but the result still same.
SELECT s.id, s.player,
COUNT(case when dg.winner = 1 AND dp.colour <= 5 then 1 when dg.winner = 2 AND dp.colour > 5 then 1 else null end) as totalwin,
COUNT(case when dg.winner = 2 AND dp.colour <= 5 then 1 when dg.winner = 1 AND dp.colour > 5 then 1 else null end) as totallose,
COUNT(dg.winner) as totalgames
FROM dotaplayers AS dp
LEFT JOIN gameplayers AS gp ON gp.gameid = dp.gameid and dp.colour = gp.colour
LEFT JOIN stats AS s ON s.player_lower = gp.name
LEFT JOIN dotagames AS dg ON dg.gameid = dp.gameid
LEFT JOIN games AS g ON g.id = dp.gameid
LEFT JOIN bans as b ON b.name=gp.name
WHERE MONTH(g.datetime) = 4
GROUP by gp.name
ORDER BY totalwin DESC LIMIT 0,10
Showing rows 0 - 9 (10 total, Query took 7.7552 seconds.)
I want order the most winner in 4th month (April). Then it shows id, username, totalwins, totallose, totaldraw, totalgames. The case in my query is the how to get that. The result is correct, but slow.
Assuming g.datetime is indexed, try this instead:
WHERE g.`datetime` BETWEEN 20150401 AND 20150430`
Using the MONTH function, or any other function, on the field data in the WHERE eliminates the benefits of any indexes you might have on those fields; this results in the query requiring a full scan of the values in the table.
Rearranging the order of JOINs will probably help as well:
SELECT s.id, s.player
, SUM(case
when dg.winner = 1 AND dp.colour <= 5 then 1
when dg.winner = 2 AND dp.colour > 5 then 1
else 0
end
) as totalwin
, SUM(case
when dg.winner = 2 AND dp.colour <= 5 then 1
when dg.winner = 1 AND dp.colour > 5 then 1
else 0
end
) as totallose
, COUNT(dg.winner) as totalgames -- Not, sure of the nature of dg.`winner`, a SUM might be more appropriate here as well.
FROM games AS g
INNER JOIN dotaplayers AS dp ON g.id = dp.gameid
LEFT JOIN gameplayers AS gp ON gp.gameid = dp.gameid and dp.colour = gp.colour
LEFT JOIN stats AS s ON s.player_lower = gp.name
LEFT JOIN dotagames AS dg ON dg.gameid = dp.gameid
LEFT JOIN bans as b ON b.name=gp.name
WHERE g.`datetime` BETWEEN 20150401000000 AND 20150430235959
GROUP by gp.name
ORDER BY totalwin DESC
LIMIT 0,10
;
Another thing to note: Depending on the relationship between tables, some of the intermediate joins may result in effectively multiplying the resulting totals; this can be resolved by doing the sums in subqueries and joining those instead.

MySQL - join same table twice

I have a table called 'booking'
> id status
1 P
2 P
and another called 'call'
id calldate type booking
1 01/01/2012 DEL 1
2 01/02/2012 COL 1
3 01/03/2012 DEL 2
4 31/12/2019 COL 999
I want to list each record in 'bookings' ONCE, showing associated records from 'call' as another column like this:
bookingId deliverydate collectiondate
1 01/01/2012 01/02/2012
2 01/03/2012 null
I've tried:
select `b`.`bookingid` AS `bookingid`,
`del`.`calldate` AS `Delivery`,
`col`.`calldate` AS `Collection`
from `booking` `b`
left join `call` `del` on `b`.`bookingid` = `del`.`booking`
left join `call` `col` on `b`.`bookingid` = `col`.`booking`
where ((`del`.`type` = 'DEL') OR (`col`.`type` = 'COL') and (`b`.`status` = 'P'));
but I get bookingid 1 listed 3 times. Can someone please fix my joins?
I think you want to move your types into the join conditions:
select `b`.`bookingid` AS `bookingid`,
`del`.`calldate` AS `Delivery`,
`col`.`calldate` AS `Collection`
from `booking` `b`
left join `call` `del` on `b`.`bookingid` = `del`.`booking` AND `del`.`type` = 'DEL'
left join `call` `col` on `b`.`bookingid` = `col`.`booking` AND `col`.`type` = 'COL'
where `b`.`status` = 'P';
You don't need to join the same table twice, you could use this:
SELECT
`call`.booking,
max(case when type='DEL' then calldate end) as deliverydate,
max(case when type='COL' then calldate end) as collectiondate
FROM
booking inner join `call`
on booking.id=`call`.booking
WHERE
booking.status='P'
GROUP BY `call`.booking