mysql group by date and left join table used group by date - mysql

I am going to query two tables now, use the left connection, first use the group by date in the main table, the date is grouped according to the week, and now I also want to use the same date to group in the join table of join. How to query this?
now I am doing this
select
case
when order.time BETWEEN '2018-7-27' and '2018-8-3' then '7.27-8.2'
when order.time BETWEEN '2018-8-3' and '2018-8-10' then '8.3-8.9'
else "--" end ptime,
payment.uid, payment.time
from order
left join
(select uid, time, from payment where create_time between '2018-7-27' and '2018-8-10') payment on payment.uid = order.uid
where order.time between '2018-7-13' and '2018-8-10'
+----------+-------+-----------------------+
| date | uid | time |
+----------+-------+-----------------------+
| 7.27-8.2 | 42 | 2018-07-27 22:08:22 |
| 7.27-8.2 | 42 | 2018-07-27 22:08:22 |
| 8.3-8.9 | 50 | 2018-08-04 14:19:00 |
| 8.3-8.9 | 50 | 2018-08-04 14:19:00 |
| 8.3-8.9 | 76 | 2018-07-28 14:20:00 |
| 8.3-8.9 | 76 | 2018-07-28 14:12:00 |
| 8.3-8.9 | 76 | 2018-07-28 13:12:00 |
| 8.3-8.9 | 88 | 2018-07-28 19:29:00 |
| 8.3-8.9 | 98 | 2018-08-09 14:39:00 |
+----------+-------+-----------------------+
except output:
+----------+-------+-----+
| date | uid | time|
+----------+-------+-----+
| 7.27-8.2 | 42 | 2 |
| 8.3-8.9 | 50 | 2 |
| 8.3-8.9 | 76 | 3 |
| 8.3-8.9 | 88 | 0 |
| 8.3-8.9 | 98 | 1 |
+----------+-------+-----+
But in this way, the payment time is not grouped according to the date of the order.
Grouping rules are still on the order table.
How do I apply a date grouping to two tables, and do the same grouping of the pay table deduplication? Thank you very much!

This is my solution:
select p1.ptime, p2.uid, count(p2.uid) (
select
case
when order.time BETWEEN '2018-7-27' and '2018-8-3' then '7.27-8.2'
when order.time BETWEEN '2018-8-3' and '2018-8-10' then '8.3-8.9'
else "--" end ptime
from order
where order.time between '2018-7-13' and '2018-8-10' group by ptime) p1
left join
(select
case
when payment.time BETWEEN '2018-7-27' and '2018-8-3' then '7.27-8.2'
when payment.time BETWEEN '2018-8-3' and '2018-8-10' then '8.3-8.9'
else "--" end p2time,
count(payment.uid) uid_cnt
from order
left join
(select uid, time, from payment where create_time between '2018-7-27' and
'2018-8-10') payment on payment.uid = order.uid
where order.time between '2018-7-13' and '2018-8-10' group by p2time) p2
on p2.p2time = p1.ptime

You just need aggregate function count
select uid,date(ptime) as date,count(payment.time) as time
from
( select
case
when order.time BETWEEN '2018-7-27' and '2018-8-3' then '7.27-8.2'
when order.time BETWEEN '2018-8-3' and '2018-8-10' then '8.3-8.9'
else "--" end ptime,
payment.uid, payment.time
from order
left join
(select uid, time, from payment where create_time between '2018-7-27' and '2018-8-10') payment on payment.uid = order.uid
where order.time between '2018-7-13' and '2018-8-10'
) as t group by uid,date(ptime)

Related

Customizing ROLLUP row mySQL

I want to summarize the sales data and I want to sum its total in the last row, I'm using "GROUP BY" and "WITH ROLLUP" but the results are:
+--------+--------------------+------------+--------+-----------+
| id | name | date | amount | total |
+--------+--------------------+------------+--------+-----------+
| Z00015 | Mebel Harmonis | 2019-05-09 | 2 | 10000000 |
| Z00016 | Mebel Harmonis | 2019-05-09 | 10 | 45000000 |
| Z00017 | Mebel Tunggal Jaya | 2019-05-10 | 3 | 12000000 |
| (null) | Mebel Tunggal Jaya | 2019-05-10 | 29 | 131000000 |
+--------+--------------------+------------+--------+-----------+
the last row that i want:
+--------+--------+--------+----+-----------+
| (null) | (null) | (null) | 29 | 131000000 |
+--------+--------+--------+----+-----------+
This is my query:
SELECT
order2.id_order AS id,
customer.name_customer AS name,
DATE( order2.date_order ) AS date ,
Count( order_detail.id_detail ) AS amount,
SUM( harga ) AS total
FROM
order_detail
INNER JOIN order2 ON order2.id_order = order_detail.id_order
INNER JOIN customer ON order2.id_customer = customer.id_customer
INNER JOIN produk ON produk.id_produk = order_detail.id_produk
INNER JOIN sofa ON sofa.id_sofa = produk.id_sofa
WHERE
date( date_order ) >= '2019-05-01'
AND date( date_order ) <= '2019-05-31'
GROUP BY
order2.id_order WITH ROLLUP;
You need to specify all the columns that can be combined together for the grand total in your GROUP BY clause:
GROUP BY id, name, date WITH ROLLUP
However, this will create intermediate subtotals for each id and id, name. You can filter them out with:
HAVING id IS NOT NULL OR (id IS NULL AND name IS NULL AND date IS NULL)

Filter and sort by a calculated column using case (column not found)

I am trying to filter and sort by a calculated column using case but I'm getting a syntax error.
Column difference_sum and column payments_sum not found
I need to be able to have a WHERE and ORDER BY clause.
I have two tables 'contracts' and 'payments'.
Contracts table
+----+-----------------+-----------+-----------+
| id | contract_number | legal_sum | bonus_sum |
+----+-----------------+-----------+-----------+
| 1 | 110258465651 | 50 | 20 |
| 2 | 564984656355 | 15 | 12 |
| 3 | 548498415165 | 150 | 35 |
+----+-----------------+-----------+-----------+
Payments table
+----+--------------+----------+
| id | contract_id | paid_sum |
+----+--------------+----------+
| 1 | 564984656355 | 7 |
| 2 | 564984656355 | 1 |
| 3 | 564984656355 | 2 |
+----+--------------+----------+
First I need to calculate the difference between legal sum and bonus sum (difference_sum)
Then I need to get the sum of payments.paid_sum (payments_sum)
Then I need to sort by the criteria if (payments_sum - difference_sum <= 0)
So I made this query but it says that difference_sum does not exist:
SELECT
(contracts.legal_sum - contracts.bonus_sum) as difference_sum
sum(payments.paid_sum) as payments_sum,
CASE
WHEN (difference_sum - payments_sum) <= 0 THEN "All paid"
WHEN (difference_sum - payments_sum) > 0 THEN "Not paid"
END AS isPaid
FROM contracts
INNER JOIN payments on contracts.id = payments.contract_id
WHERE isPaid = "All paid"
ORDER BY isPaid
Example output:
+----------------+--------------+----------+
| difference_sum | payments_sum | isPaid |
+----------------+--------------+----------+
| 30 | 30 | All paid |
| 48 | 15 | Not paid |
| 100 | 100 | All paid |
+----------------+--------------+----------+
Try
SELECT difference_sum, payments_sum, isPaid
FROM (
SELECT payments_sum,
(contracts.legal_sum - contracts.bonus_sum) as difference_sum
CASE
WHEN (contracts.legal_sum - contracts.bonus_sum - payments_sum) <= 0 THEN "All paid"
WHEN (contracts.legal_sum - contracts.bonus_sum - payments_sum) > 0 THEN "Not paid"
END AS isPaid
FROM contracts
INNER JOIN (
SELECT contract_id, sum(payments.paid_sum) as payments_sum
FROM payments
GROUP BY contract_id
) payments on contracts.id = payments.contract_id
) q
WHERE isPaid = "All paid"
-- why order by a single value ?
-- ORDER BY isPaid
Probably you also need to add contract_id column to make it more useful.

How to sum the value and retrieve the result using if condition- using MySQL?

I want to sum every time and check with if condition. If condition matches I want the get the created date of the final matched row.
+------------+----------------------------------+------------+--------+
| id | EMAIL | created | Amt |
+------------+----------------------------------+------------+--------+
| 61 | abc#gmail.com | 1514909390 | 57.00 |
| 25 | xyz#gmail.com | 1515534837 | 360.00 |
| 36 | zccc#abv.com | 1515645391 | 240.00 |
| 22 | vv#aa.com | 1516419622 | 320.40 |
| 48 | aa#xyz.com | 1516706121 | 240.00 |
+------------+----------------------------------+------------+--------+
I try this query but I'm not getting the solution...
select
sum(a.amount) as amt,
if(sum(a.amount)>8000,slp.sal_time,0) as Amt_exceed_date
from employee a
join emp_user u
on a.cmp_id=u.user_id
left join emp_sal as slp
on slp.user_id=a.cmp_id
where
order by slp.sal_time;
Somewhat like row wise sum
select e.*,(
select sum(Amt)
from employee
where created <= e.created
) row_wise_sum
from employee e
having row_wise_sum < 800
order by e.created
desc limit 1
Demo

Using left join with min

I am trying to connect two tables with left join and a date.
My SQL Query
SELECT
ord.`ordernumber` bestellnummer,
his.`change_date` zahldatum
FROM
`s_order` ord
LEFT JOIN
`s_order_history` his ON ((ord.`id`=his.`orderID`) AND (ord.`cleared`=his.`payment_status_id`)) #AND MIN(his.`change_date`)
WHERE
ord.`ordertime` >= \''.$dateSTART.'\' AND ord.`ordertime` <= \''.$dateSTOP.'\'' ;
s_order
+----+---------------------+---------+-------------+
| id | ordertime | cleared | ordernumber |
+----+---------------------+---------+-------------+
| 1 | 2014-08-11 19:53:43 | 2 | 123 |
| 2 | 2014-08-15 18:33:34 | 2 | 125 |
+----+---------------------+---------+-------------+
s_order_history
+----+-------------------+-----------------+---------+---------------------+
| id | payment_status_id | order_status_id | orderID | orderID change_date |
+----+-------------------+-----------------+---------+---------------------+
| 1 | 1 | 5 | 1 | 2014-08-11 20:53:43 |
| 2 | 2 | 5 | 1 | 2014-08-11 22:53:43 |
| 3 | 2 | 7 | 1 | 2014-08-12 19:53:43 |
| 4 | 1 | 5 | 2 | 2014-08-15 18:33:34 |
| 5 | 1 | 6 | 2 | 2014-08-16 18:33:34 |
| 6 | 2 | 6 | 2 | 2014-08-17 18:33:34 |
+----+-------------------+-----------------+---------+---------------------+
Wanted result:
+-------------+---------------------+
| ordernumber | change_date |
+-------------+---------------------+
| 123 | 2014-08-11 22:53:43 |
| 125 | 2014-08-17 18:33:34 |
+-------------+---------------------+
The problem I have is getting only the date, where the cleared/payment_status_id value has been changed in s_order. I currently get all dates where the payment_status_id matches the current cleared value, but I only need the one, where it happend first.
This is only an excerpt of the actually query, since the original is a lot longer (mostly more left joins and a lot more tables).
You can group data by ordernumber
SELECT
ord.`ordernumber` bestellnummer,
MIN(his.`min_change_date`) as zahldatum
FROM
`s_order` ord
LEFT JOIN
`s_order_history` his ON ((ord.`id`=his.`orderID`) AND (ord.`cleared`=his.`payment_status_id`)) #AND MIN(his.`change_date`)
WHERE
ord.`ordertime` >= \''.$dateSTART.'\' AND ord.`ordertime` <= \''.$dateSTOP.'\''
GROUP BY
ord.`ordernumber`;
or you can group data in a subquery:
SELECT
ord.`ordernumber` bestellnummer,
his.`min_change_date` zahldatum
FROM
`s_order` ord
LEFT JOIN (
SELECT
orderID, payment_status_id, MIN(change_date) as min_change_date
FROM
s_order_history
GROUP BY
orderID, payment_status_id
) his ON (ord.`id` = his.`orderID` AND ord.`cleared` = his.`payment_status_id`)
WHERE
ord.`ordertime` >= \''.$dateSTART.'\' AND ord.`ordertime` <= \''.$dateSTOP.'\'';
Try this:
select s_order.ordernumber, min(s_order_history.change_date)
from s_order left join s_order_history
on s_order.id = s_order_history.orderID
and s_order.cleared = s_order_history.payment_status_id
group by s_order.order_id
SELECT ord.`ordernumber` bestellnummer,
MIN( his.`change_date` ) zahldatum
...
GROUP BY ord.`ordernumber`
MIN is an aggregate function so you can't use it in a JOIN straight up like you've tried above. You also are not comparing it to a value in your JOIN.
You'll want to do something like:
his.`change_date` = (SELECT MIN(his.`change_date`) FROM s_order_history where ord.`id` = his.`orderID`)
in your JOIN.

SQL Help: How come the total from this query is different that a summation query?

This query does a group by on lead_source_id:
SELECT ch.lead_source_id,
Count(DISTINCT ch.repurchased_date)
FROM customers_history ch
WHERE ch.repurchased_date >= '2014-04-01'
AND ch.repurchased_date < '2014-05-01'
AND ch.lead_source_id IS NOT NULL
GROUP BY ch.lead_source_id;
And this query totals the records in the table:
SELECT Count(DISTINCT( repurchased_date ))
FROM customers_history
INNER JOIN (SELECT DISTINCT( customer_id ) AS xcid
FROM customers_history
WHERE repurchased_date >= '2014-04-01'
AND repurchased_date < '2014-05-01'
AND lead_source_id IS NOT NULL) AS Temp
ON Temp.xcid = customer_id
WHERE repurchased_date >= '2014-04-01'
AND repurchased_date < '2014-05-01'
AND lead_source_id IS NOT NULL;
On our production data, the totals from Query1 come to 7963, but the second query prints 7905. Why the difference and how can we fix our queries?
Here's our table layout:
+--------+-------------+----------------+---------------------+--------+
| id | customer_id | lead_source_id | repurchased_date | Rating |
+--------+-------------+----------------+---------------------+--------+
| 422923 | 420450 | 4 | 2014-04-14 09:16:48 | Warm |
| 422924 | 420450 | 4 | 2014-04-14 09:16:48 | Cold |
| 422956 | 420450 | 4 | 2014-04-14 09:16:49 | Hot |
| 422933 | 420451 | 37 | 2014-04-14 09:18:41 | Hot |
| 422938 | 420452 | 1 | 2014-04-10 20:50:30 | Hot |
| 422984 | 420452 | 1 | 2014-04-12 20:50:30 | Warm |
| 422940 | 420453 | 47 | 2014-04-14 09:20:27 | Hot |
+--------+-------------+----------------+---------------------+--------+
EDIT
To answer some of the possibilities about nulls:
select count(id) from customers_history where customer_id is null: 0
select count(id) from customers_history where lead_source_id is null: 5103
select count(id) from customers_history where repurchased_date is null: 0
The most obvious conclusion is that some lead_source_ids share values of repurchased_date.
Another possibility is that you have NULL values for customer_id and the second filters these out.
The third possibility is that NULL values of lead_source_id are adding additional values in the first query.