I have two tables
customers (id, name....,created_at)
coupons (id, customer_id, ....,created_id)
I am trying to get count of all those coupons where created_at is 2015-12-29 and where customer's created_at is not 2015-12-29
select
count(*) as aggregate
from
`coupons`
where
(select count(*) from `customers`
where
`coupons`.`customer_id` = `customers`.`id`
and
DATE(`customers`.`created_at`) <> '2015-12-29') >= 1
and
DATE(`updated_at`) = '2015-12-29'
This query works fine, but when I add one more constraint to query client_id = 1, it doesnot work.
select
count(*) as aggregate
from
`coupons`
where
(select count(*) from `customers`
where
`coupons`.`customer_id` = `customers`.`id`
and
DATE(`customers`.`created_at`) <> '2015-12-29') >= 1
and
DATE(`updated_at`) = '2015-12-29'
and
`client_id` = 1
It should return non zero value, but it returns 0
Dummy data
customers
id, name, created_at
1 ehsan 2015-12-29 12:10:10
2 ehs 2015-12-28 12:10:10
coupons
id, customer_id, updated_at client_id
1 1 2015-12-29 12:10:10 1
2 2 2015-12-29 12:10:10 1
3 2 2015-12-29 12:10:10 1
Related
I've this table
order_status_history, I insert a row everytime an order is updated, and let's say a table orders with only the column id:
id
order_id
order_status_id
updated_at
1
121
ready
2021-12-30 10:00:00
2
121
shipped
2021-12-30 10:01:00
3
121
ready
2021-12-30 10:02:00
4
121
shipped
2021-12-30 10:03:00
5
121
delivered
2021-12-30 10:04:00
I need to get the latest updated_at value for all the orders (DISTINCT) that have been shipped as last status, or delivered if for any reason there is no shipped status .
I wrote this query, but I get the last updated_at value of the delivered status. In the example case I need the updated_at as 10:03, but I get the 10:04 one.
SELECT o.id,
osh.max_updated_at AS updatedAt
FROM orders o
JOIN ( SELECT order_id,
Max(updatedat) AS max_updated_at
FROM order_status_history
WHERE order_status_id IN('shipped','delivered')
GROUP BY order_id
) AS osh ON osh.order_id = o.id
AND ( SELECT order_status_id
FROM order_status_history
WHERE order_id = o.id
ORDER BY updatedat DESC
LIMIT 1
) IN('shipped','delivered')
Try this one with subquery
SELECT id, (
SELECT h.updated_at
FROM order_status_history h
WHERE h.order_id = o.id
AND h.order_status_id IN ('shipped','delivered')
AND NOT EXISTS (
SELECT 1
FROM order_status_history k
WHERE k.order_id = h.order_id
AND k.updated_at > h.updated_at
AND k.order_status_id NOT IN ('shipped','delivered')
)
ORDER BY CASE WHEN order_status_id = 'shipped' THEN 1 ELSE 2 END ASC, updated_at DESC
LIMIT 1
) AS updatedAt
FROM orders o
Subquery works if you select a single column
This is another option for MySQL8+
WITH ordered AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY order_id ORDER BY CASE WHEN order_status_id = 'shipped' THEN 1 ELSE 2 END ASC, updated_at DESC) rn
FROM order_status_history
WHERE order_status_id IN ('shipped','delivered')
)
SELECT o.id, h.*
FROM orders o
LEFT JOIN ordered h ON o.id = h.order_id
AND h.rn = 1 AND NOT EXISTS (
SELECT 1
FROM order_status_history k
WHERE k.order_id = h.order_id
AND k.updated_at > h.updated_at
AND k.order_status_id NOT IN ('shipped','delivered')
)
I need to update row which having same value in debit column & only row which having create_date ASC basically 2019-11-15
I am having transaction table with following data
table name - tbl_transactions
id client_id user_id debit add_date
1 9991101 1 7.69 2019-11-15
2 9991101 1 7.69 2019-11-30
3 9991101 2 28.9 2019-11-15
4 9991101 2 11.49 2019-11-30
5 9991101 3 17.09 2019-11-15
6 9991101 3 17.09 2019-11-30
Now i just want to UPDATE record which have same value in column "debit" & date "2019-11-15"
which means only id-1 will be get updated.
id client_id user_id debit add_date
1 999110100 1 7.69 2019-11-15
5 999110100 3 17.09 2019-11-15
We can add additional 00 to client_id field, i have tried with below sql but seems its not working
UPDATE tbl_transactions SET client_id=999110100 WHERE id IN ( SELECT * FROM tbl_transactions WHERE client_id=9991101 AND DATE(create_date)='2019-11-15' GROUP BY user_id, debit HAVING COUNT(*) = 2 )
Thanks in advance.
for select you should use
select user_id, debit
from tbl_transactions
INNER JOIN (
select distinct user_id
from tbl_transactions
where add_date = "2019-11-15"
) t2 on t2.user_id = a.user_id
group by user_id, debit
HAVING COUNT(*) = 2
for update you could use
update tbl_transactions a
INNER JOIN (
select user_id, debit
from tbl_transactions
INNER JOIN (
select distinct user_id
from tbl_transactions
where add_date = "2019-11-15"
) t2 on t2.user_id = a.user_id
group by user_id, debit
HAVING COUNT(*) = 2
) t on t.user_id = a.usre_id
and t.debit = a.debit
set your_column = 'your_values'
I'm running a query that selects details of orders, and I want to see only the orders that have gone through multiple stages. My data looks like:
id | order_id | action
1 100 1
2 100 2
3 100 4
4 101 1
5 102 2
6 103 1
7 103 2
So that only the rows for order_id 100 and 103 will be selected. This needs to be nested in a larger query.
You can use a subquery to get the orders that had multiple stages:
SELECT order_id
FROM your_table
GROUP BY order_id
HAVING COUNT(*)>1
then you can join this result back to your table:
SELECT o.*
FROM yourtable AS o INNER JOIN (
SELECT order_id
FROM your_table
GROUP BY order_id
HAVING COUNT(*)>1
) dup ON o.order_id = dup.order_id
Use group by with count and having
select *,count(order_id) as total from table
group by order_id
having total > 1
you can try this query:
select * from your_table
where ( select count(*) from your_table internal_table
where your_table .order_id = internal_table.order_id
) > 1
I need to merge multiple table group by the count base on date's day.
Below are my table structure :
#table1
id date
1 2015-07-01 00:00:00
2 2015-07-02 00:00:00
3 2015-07-03 00:00:00
#table2
id date
1 2015-07-02 00:00:00
2 2015-07-02 00:00:00
3 2015-07-02 00:00:00
4 2015-07-10 00:00:00
What I wanted to achieve :
#query result
date t1_count t2_count
2015-07-01 1 NULL
2015-07-02 1 3
2015-07-03 1 NULL
2015-07-10 NULL 1
Below are my query that refer to this link:
SELECT left(A.date,10) AS `day`
, COUNT(A.ID) AS `a_count`
, COUNT(B.ID) AS `b_count`
FROM table1 A
LEFT JOIN table2 B
ON LEFT(A.date,10) = LEFT(B.date,10)
GROUP BY LEFT(A.date,10)
UNION
SELECT left(B.date,10) AS `day`
, COUNT(A.ID) AS `a_count`
, COUNT(B.ID) AS `b_count`
FROM table1 A
RIGHT JOIN table2 B
ON LEFT(A.date,10) = LEFT(B.date,10)
GROUP BY LEFT(A.date,10);
but the result was
#query result
date t1_count t2_count
2015-07-01 1 0
2015-07-02 3 3
2015-07-03 1 0
2015-07-10 0 1
I'd try to modified and search other solution like UNION ALL, LEFT JOIN, etc, but I'd no luck to solve this problem.
You can do this using union all and group by:
select date, sum(istable1) as numtable1, sum(istable2) as numtable2
from ((select date(date) as date, 1 as istable1, NULL as istable2
from table1
) union all
(select date(date) as date, NULL as istable1, 1 as istable2
from table2
)
) t
group by date
order by 1;
Under some circumstances, it can be faster to aggregate the data in the subqueries as well:
select date, sum(numtable1) as numtable1, sum(numtable2) as numtable2
from ((select date(date) as date, count(*) as numtable1, NULL as numtable2
from table1
group by date(date)
) union all
(select date(date) as date, NULL as numtable1, count(*) as numtable2
from table2
group by date(date)
)
) t
group by date
order by 1;
If you want 0 instead of NULL in the desired results, use 0 instead of NULL in the subqueries.
I have two tables. One for employees and another for ratings. Some employees have been rated others not. I'm trying to list all the employees with or without a rating value and sort them from the highest rating.
emp table
empid empName
--------------
1 John
2 Alex
3 Peter
4 Mary
Ratings table
ratingid | customerid | ratingvalue | empid
---------------------------------------------
1 1 4 1
2 6 2 1
3 4 3 3
4 5 5 4
Expected output:
empid | empName | avgrating | ratingcount
---------------------------------------------
1 John 3 2
2 Alex 0 0
3 Peter 3 1
4 Mary 5 1
I tried
SELECT *, round(AVG(ratingvalue ), 2) as avgrating, count(empid) as ratingcount
FROM emp LEFT JOIN ratings ON emp.empid = ratings.empid ORDER BY `avgrating`
DESC
That query doesn't produce the result I expect. It only gives me one row.
Thanks in advance
need group by and coalesce null values to 0.
SELECT EmpID, empName,
coalesce(round(AVG(ratingvalue ), 2),0) as avgrating,
coalesce(count(empid),0) as ratingcount
FROM emp
LEFT JOIN ratings
ON emp.empid = ratings.empid
GROUP BY EmpID, EmpName
ORDER BY `avgrating`DESC
I think this is what you want.
select
e.id, e.name,
avg(coalesce(t1.rating,0)) average_rating,
count(coalesce(t1.rating,0)) count_rating
from
(select '1' id, 'John' name union all
select '2' id, 'Alex' name union all
select '3' id, 'Peter' name union all
select '4' id, 'Mary' name) e
left join (select '1' id, '1' customer_id, '4' rating, '1' emp_id union all
select '2' id, '6' customer_id, '2' rating, '1' emp_id union all
select '3' id, '4' customer_id, '3' rating, '3' emp_id union all
select '4' id, '5' customer_id, '5' rating, '4' emp_id) t1 on
t1.emp_id = e.id
group by
e.id,
e.name
I have just subbed out your tables for data. You can run this in mysql directly and it should give you want you want.