MYSQL Query : How to UNION two table with ORDER BY - mysql

can anyone help me solve this problem? i've been trying to query this but i keep getting error.
MySQL code:
SELECT * FROM
(
SELECT BU.*, BD.BOOK_TITLE AS BOOK_TITLE, BD.BOOK_COMPANY AS COMPANY,
BD.RETURN_DATE AS RETURN
FROM BOOK_USER BU
INNER JOIN BOOKING_DETAIL BD ON (BU.USR_ID = BD.USR_ID)
UNION
SELECT BU.*, "NEW REGISTERED" AS BOOK TITLE, 'RENT-A-BOOK' AS COMPANY,
BU.REGISTER_DATE AS RETURN
FROM BOOK_USER BU
) AS BU
GROUP BY BU.USR_ID
The Tables:
BOOK_USER
+---------+----------+---------------+
| USR_ID | USR_NAME | REGISTER_DATE |
+---------+----------+---------------+
| 1 | john | 2011-09-20 |
+---------+----------+--------------+
| 2 | jane | 2011-12-05 |
+---------+----------+--------------+
| 3 | doe | 2012-02-16 |
+---------+----------+--------------+
| 4 | mary | 2012-02-02 |
+---------+----------+--------------+
BOOKING_DETAIL
+---------+----------+------------+-----------+--------------+
| BOOK_ID | USR_ID | BOOK_TITLE | COMPANY | RETURN_DATE |
+----------+--------+-------------+-----------+--------------+
| 1 | 1 | DEAR JOHN |ABC PVT LMT| 2011-11-01 |
+---------+---------+-------------+-----------+--------------|
| 2 | 1 | LUCKY | DEF | 2012-03-18 |
+---------+---------+-------------+-----------+--------------|
| 3 | 1 | THE RISE | GHI | 2012-06-12 |
+---------+---------+-------------+-----------+--------------|
| 4 | 2 | HELLO | TIMES | 2012-01-11 |
+---------+---------+-------------+-----------+--------------|
| 5 | 2 | SHOPAHOLIC | | 2012-08-31 |
+---------+---------+-------------+-----------+--------------|
| 6 | 3 | LOST | | 2012-06-20 |
+---------+---------+-------------+-----------+--------------|
The result should return the latest RETURN_DATE and SORTED by USR_ID.
eg:
John, THE RISE, GHI,2012-06-12
Jane,SHOPAHOLIC,RENT-A-BOOK,2012-08-31
doe, LOST,RENT-A-BOOK,2012-06-20
mary, NEW REGISTERED,RENT-A-BOOK , 2012-02-02

The query constains a subquery which gets the latest RETURN_DATE for each user.
SELECT a.*, c.BOOK_TITLE, c.RETURN_DATE
FROM book_user a
INNER JOIN
(
SELECT usr_ID, MAX(return_DATE) maxDate
FROM booking_detail
GROUP BY usr_ID
) b ON a.usr_ID = b.usr_ID
INNER JOIN booking_detail c
ON b.usr_ID = c.usr_ID AND
b.maxDate = c.return_DATE
SQLFiddle Demo
UPDATE
use LEFT JOIN and COALESCE
SELECT a.USR_ID,
a.USR_NAME,
COALESCE(c.BOOK_TITLE,'RENT-A-BOOK') BOOK_TITLE,
COALESCE(c.RETURN_DATE, a.REGISTER_DATE) RETURN_DATE
FROM book_user a
LEFT JOIN
(
SELECT usr_ID, MAX(return_DATE) maxDate
FROM booking_detail
GROUP BY usr_ID
) b ON a.usr_ID = b.usr_ID
LEFT JOIN booking_detail c
ON b.usr_ID = c.usr_ID AND
b.maxDate = c.return_DATE
SQLFiddle Demo

Try that :
SELECT *
FROM (
(
SELECT BU.*, BD.BOOK_TITLE, BD.BOOK_COMPANY AS COMPANY,BD.RETURN_DATE AS RETURN FROM BOOK_USER BU INNER JOIN BOOKING_DETAIL BD ON (BU.USR_ID = BD.USR_ID)
) UNION ALL (
SELECT BU.*, BD.BOOK_TITLE, 'RENT-A-BOOK' AS COMPANY,BD.RETURN_DATE AS RETURN FROM BOOK_USER BU INNER JOIN BOOKING_DETAIL BD ON (BU.USR_ID = BD.USR_ID)
)
) BU
GROUP BY BU.USR_ID

You can directly get the output using following query check the query:
SELECT BU.*, IFNULL(BD.BOOK_TITLE, 'NEW REGISTERED') AS BOOK_TITLE, IFNULL(BD.BOOK_COMPANY, 'RENT-A-BOOK') AS COMPANY,BD.RETURN_DATE AS RETURN
FROM BOOK_USER BU
LEFT JOIN (SELECT * FROM (SELECT USR_ID, BOOK_TITLE, BOOK_COMPANY, RETURN_DATE FROM BOOKING_DETAIL ORDER BY RETURN_DATE DESC) AS A GROUP BY USR_ID) AS BD ON (BU.USR_ID = BD.USR_ID)
ORDER BY BU.USR_ID;

Related

How to select only last matching result if this is equal to x from mysql table

i've three tables in my mysql database:
orders table (example):
orders
id | user_id | price
1 | 10 | 29.99
2 | 20 | 29.99
3 | 30 | 29.99
4 | 40 | 29.99
users table:
users
id | name | surname
10 | mark | white
20 | john | long
30 | anders | red
40 | john | smith
and orders_updates table
orders_updates
id | order_id | status_id | date
1 | 1 | 1 | 03/05/2020
2 | 1 | 2 | 04/05/2020
3 | 2 | 1 | 05/05/2020
4 | 3 | 1 | 06/05/2020
5 | 4 | 1 | 06/05/2020
6 | 4 | 2 | 06/05/2020
What i need:
new orders
order_id | user_id | name | surname
2 | 20 | john | long
3 | 30 | anders | red
Now, i need to create the "new orders" page (orders_updates.status_id = 1), how i can get only orders with only status_id=1 and not some other status_id.
This is where i'm stuck:
SELECT o.*, u.*
FROM orders o, users u, orders_updates ou
WHERE o.user_id = u.id
AND (SELECT MAX(ID) FROM order_updates WHERE order_updates.order_id = o.id)
AND ou.order_id = o.id
Thank you all.
Try the following
select
order_id,
user_id,
name,
surname
from orders_updates ou
join orders o
on ou.order_id = o.id
join users u
on u.id = o.user_id
where ou.status_id = 1
order by
order_id
I would go with:
select
order_id,
user_id,
name,
surname
from orders_updates ou
join orders o
on ou.order_id = o.id
join users u
on u.id = o.user_id
where ou.status_id = 1
and ou.order_id not in (
select distinct order_id
from orders_updates
where status_id in (2,3)
)
order by
order_id
I put as a sample status_id in (2,3) but you should include there all the other status_ids you don’t want to be considered.
Hope that helps!

Find the number of users who made their first order in each country, each day

I have 2 tables which looked like:
user_dataset
+------+---------------+------------+
|userid| Register_time | Country |
+------+---------------+------------+
| 1 | 03/02/17 | TW |
| 2 | 20/03/17 | SG |
| 3 | 26/03/17 | PH |
| 4 | 05/02/17 | VN |
| 5 | 01/10/17 | ID |
| 6 | 03/09/17 | MY |
| ...| ........ | ... |
+------+---------------+------------+
order_dataset
+--------+--------+------------+--------+------------+
|orderid | userid | itemid | gmv | order_time |
+--------+--------+------------+--------+------------+
|1030132 | 3 | 3366770 | 27,0 | 24/04/17 |
|1030137 | 5 | 6130641 | 69,0 | 02/02/17 |
|1030147 | 1 | 6770063 | 87,0 | 25/04/17 |
|1030153 | 6 | 4193426 | 82,0 | 05/11/17 |
|1030155 | 4 | 8825994 | 29,0 | 03/07/17 |
|1030160 | 2 | 5660916 | 44,0 | 30/01/17 |
|....... | ... | ... | ... | ... |
+--------+--------+------------+--------+------------+
I have been told to Write a SQL statement to find the number of users who made their first order in each country, each day.
I don't understand the question, can someone explain to me what the output looks like? I'm not asking the Queries but if someone willing to write it would be wonderful tho.
Thank you in advance
Join the table user_dataset to a query that returns from order_dataset the date of the 1st order of each userid and aggregate:
select u.country, o.order_time, count(*) counter
from user_dataset u inner join (
select userid, min(order_time) order_time
from order_dataset
group by userid
) o on o.userid = u.userid
group by u.country, o.order_time
If there is a case a user has placed 2 orders at the same day, then instead of count(*) use count(distinct userid).
SELECT a.userid, a.purchase_time,c.country
FROM purchase_tab a
INNER JOIN
(SELECT userid, MIN(purchase_time) As first_occurence
FROM purchase_tab
GROUP BY userid) b
ON a.userid = b.userid AND a.purchase_time = b.first_occurence
INNER JOIN user_tabs c
ON a.userid=c.userid
ORDER BY a.userid
SELECT
country,
order_time,
COUNT(*)
FROM user u
LEFT JOIN(
SELECT
userid,
MIN(order_time) AS min_date
FROM order
GROUP BY userid
) o
ON u.userid = o.userid
LEFT JOIN order ot
ON u.userid = ot.userid
WHERE order_time = min_date
GROUP BY country, order_time
ORDER BY country;

Get default value from JOIN query if join field value doesn't exist in another table

I have two tables customers and reviews. The structure is like this:
customers:-
|---------------------------------|
| id | name |
|---------------------------------|
| 1 | Thutmekri |
|---------------------------------|
| 3 | Conan |
|---------------------------------|
reviews:-
|-------------------------------------------|
| id | business_id | customer_id |
|-------------------------------------------|
| 1 | 1 | 1 |
|-------------------------------------------|
| 2 | 1 | 2 |
|-------------------------------------------|
| 3 | 1 | 3 |
|-------------------------------------------|
customer_id of reviews is id of customer.
The join query,
SELECT customers.name, reviews.id as review_id
FROM customers, reviews
WHERE customers.id = reviews.customer_id
returns the dataset like this:-
|----------------------------------|
| review_id | name |
|----------------------------------|
| 1 | Thutmekri |
|----------------------------------|
| 3 | Conan |
|----------------------------------|
But I want it to return:-
|----------------------------------|
| review_id | name |
|----------------------------------|
| 1 | Thutmekri |
|----------------------------------|
| 2 | N/A |
|----------------------------------|
| 3 | Conan |
|----------------------------------|
For customer_id in reviews, which doesn't have any data in customers table, I want 'N/A' to be displayed. How can I do it?
The following query also didn't help
SELECT reviews.id as review_id, COALESCE( name, 'N/A' )
FROM customers, reviews
WHERE customers.id = reviews.customer_id
Use a left join and switch the order of the tables in the join:
SELECT
r.id AS review_id,
COALESCE(c.name, 'N/A') AS name
FROM reviews r
LEFT JOIN customers c
ON c.id = r.customer_id;
SQLFiddle
Try this :
SELECT r.id as review_id, COALESCE( c.name, 'N/A' ) FROM reviews r
LEFT JOIN customers c ON c.id = r.customer_id
Use the Right outer join to achieve this:
SELECT
reviews.id as review_id,
COALESCE(name, 'N/A' )
FROM customers
RIGHT JOIN reviews
ON customers.id = reviews.customer_id;
You can use below query
SELECT
R.id AS review_id,
COALESCE(C.name, 'N/A') AS name FROM reviews R LEFT JOIN customers C ON R.customer_id = C.id ;

Calculate sum on the records while joining two tables with a third table

I have three tables:
mysql> select * from a;
+----+---------+
| ID | Name |
+----+---------+
| 1 | John |
| 2 | Alice |
+----+---------+
mysql> select * from b;
+------+------------+----------+
| UID | date | received |
+------+------------+----------+
| 1 | 2017-10-02 | 5 |
| 1 | 2017-09-30 | 1 |
| 1 | 2017-09-29 | 4 |
+------+------------+----------+
mysql> select * from c;
+------+------------+------+
| UID | date | sent |
+------+------------+------+
| 1 | 2017-09-25 | 7 |
| 1 | 2017-09-30 | 2 |
| 1 | 2017-09-29 | 3 |
+------+------------+------+
If I try to calculate the total number of sent for John, it would be 12. And for received, it would be 10.
But if I try to join all three tables, the result is weird. Here is my query to join three tables:
mysql> select sum(sent), sum(received) from a
-> join c on c.UID = a.ID
-> join b on b.UID = a.ID
-> where a.ID = 1;
+-----------+---------------+
| sum(sent) | sum(received) |
+-----------+---------------+
| 36 | 30 |
+-----------+---------------+
But I need correct numbers (12 and 10, respectively). How can I have correct numbers?
You should join the aggregated result and not the raw tables
select a.uid, t1.received, t2.sent
from a
inner join (
select uid, sum(received) received
from b
group by uid
) t1 on t1.uid = a.id
inner join (
select uid, sum(sent) sent
from c
group by uid
) t2 on t2.uid = a.id
where a.id = 1
You could try below
select bx.id, recieved, sum(c.sent) sent from
(
SELECT a.id, sum(b.received) recieved
from a
INNER JOIN b
ON a.id=b.uid
group by a.id
) bx
INNER JOIN c
ON c.uid=bx.id
group by bx.id, bx.recieved;
>>>Demo<<<
This gets rid of the subquery, but introduces something else you might not want:
( SELECT uid, 'Received' AS direction, SUM(received) AS HowMany
WHERE uid = 1
GROUP BY uid )
UNION ALL
( SELECT uid, 'Sent' AS direction, SUM(sent) AS HowMany
WHERE uid = 1
GROUP BY uid )

MySQL join and sum issue / combine queries

I have created a points example to demonstrate my issue.
A members can reward other members points, I am trying to build a query which will display the points a user has and points user has given.
Database Example
Members,
+----+----------+
| id | username |
+----+----------+
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
+----+----------+
Points,
+-------+--------+--------+
| IDFor | IDFrom | Pointz |
+-------+--------+--------+
| 1 | 2 | 5 |
| 1 | 2 | 5 |
| 3 | 1 | 2 |
+-------+--------+--------+
The return I am looking for is,
+-----------+--------+-------+
| username | Pointz | Given |
+-----------+--------+-------+
| user1 | 10 | 2 |
| user2 | 0 | 10 |
| user3 | 2 | 0 |
+-----------+--------+-------+
Both my queries return,
+-----------+--------+-------+
| username | Pointz | Given |
+-----------+--------+-------+
| user1 | 10 | 4 |
| user2 | 0 | 10 |
| user3 | 2 | 0 |
+-----------+--------+-------+
http://sqlfiddle.com/#!2/32ae6/6
SELECT a.`username`, sum(a.`Pointz`), sum(b.`Pointz`) FROM
(SELECT * FROM `members`
LEFT JOIN `Example`.`Points` AS p ON `members`.`id` = p.`IDFor` ) AS a
LEFT JOIN
(SELECT * FROM `members`
LEFT JOIN `Example`.`Points` AS n ON `members`.`id` = n.`IDFrom` ) AS b
ON a.id = b.id
GROUP BY a.`id`
http://sqlfiddle.com/#!2/32ae6/7
SELECT `members`.`username`,sum(p.`Pointz`),sum(n.`Pointz`)
FROM `members`
LEFT JOIN `Example`.`Points` as p ON p.`IDFor` = `members`.`id`
LEFT JOIN `Example`.`Points` as n ON n.`IDFrom` = `members`.`id`
GROUP BY `members`.`id`
Seems to be a common question that pops up but have not found a solution, all my other attempts from similar questions have not ended well, Thanks all.
This is what u want
select a.username, ifnull(Pointz, 0) Pointz, ifnull(Given, 0) Given from
(SELECT id, `username`, sum(`Pointz`) Pointz FROM `members`
LEFT JOIN `Points` ON `members`.`id` = `Points`.`IDFor` group by id) a
left join
(SELECT id, `username`, sum(`Pointz`) Given FROM `members`
LEFT JOIN `Points` ON `members`.`id` = `Points`.`IDFrom` group by id) b
on a.id = b.id
Try:
SELECT m.username,
COALESCE( pr.preceived, 0 ) as Pointz,
COALESCE( pg.pgiven, 0 ) as Given
FROM members m
LEFT JOIN ( SELECT IDFor, sum(pointz) as preceived
FROM Points
GROUP BY IDFor ) pr
ON m.id = pr.IDFor
LEFT JOIN ( SELECT IDFrom, sum(pointz) as pgiven
FROM Points
GROUP BY IDFrom ) pg
ON m.id = pg.IDFrom
http://sqlfiddle.com/#!2/32ae6/48
Try this:
SELECT m.`username`,
ifnull((SELECT sum(`Pointz`) FROM Points p
WHERE p.IDFor = m.id ), 0),
ifnull((SELECT sum(`Pointz`) FROM Points p
WHERE p.IDFrom = m.id ), 0)
FROM Members m
SQLFiddle