I am faced with a complicated problem of taking difference in values in rows.
Sales column shows in total sales and it is automatically updated. I would like create a table with column SalesUpdate where it takes the difference in Sales from the two most recent Sales value in TABLE 1.
TABLE 1.
№ | Date | Product | Sales
----------------------------------------
1 | 2017-03-01 | Coke | 10
2 | 2017-03-02 | Pepsi | 9
3 | 2017-03-03 | Tea | 12
4 | 2017-03-04 | Coke | 20
5 | 2017-03-05 | Coke | 22
6 | 2017-03-06 | Pepsi | 15
TABLE 2.
№ | Product | Date | SalesUpdate
---------------------------------------------------------------
1 | Coke | 2017-03-01 | 22-20 = 2
2 | Pepsi | 2017-03-02 | 15-9 = 6
3 | Tea | 2017-03-03 | 12-0 = 12
Not quite elegant solution, but, at least, not DBMS-specific :) Also, didn't get, what data you want to receive in Date column of resulting set.
SELECT md.product,
md.max_Date Date,
(t1.sales - CASE WHEN t2.sales IS NULL THEN 0 ELSE t2.sales END) SalesUpdate
FROM (SELECT MAX(DATE) max_date,
product
FROM TABLE1
GROUP BY PRODUCT) md
INNER JOIN TABLE1 t1 ON md.product = t1.product AND md.max_date = t1.DATE
LEFT JOIN TABLE1 t2 ON t2.product = t1.product AND t2.date < t1.date
LEFT JOIN TABLE1 t3 ON t2.product = t3.product AND t3.date > t2.date AND t3.date < t1.date
WHERE t3.product IS NULL
Related
I have rows in my table like this
+----+-------+--------+--------------+---------------------+
| id | cid | number | value | date |
+----+-------+--------+--------------+---------------------+
| 2 | 1 | 55 | two to one | 2020-04-19 11:25:52 |
| 2 | 9 | 56 | two to nine | 2020-04-19 11:26:04 |
| 1 | 2 | 57 | one to two | 2020-04-19 11:27:02 |
| 9 | 2 | 58 | nine to two | 2020-04-19 11:28:01 |
+----+-------+--------+--------------+---------------------+
What is the sql code to show like this
+----+-------+--------+--------------+---------------------+
| id | cid | number | value | date |
+----+-------+--------+--------------+---------------------+
| 1 | 2 | 57 | one to two | 2020-04-19 11:27:02 |
| 9 | 2 | 58 | nine to two | 2020-04-19 11:28:01 |
+----+-------+--------+--------------+---------------------+
That is mean just show latest row and make the id with cid is same like id=1-cid=2 is same with id=2-cid=1. Anybody please help and i hope you are know what i mean. Thank you so much
You can use a derived table to generate a list of latest date values for each combination of id and cid values, using LEAST and GREATEST to map (for example) (1, 2) to (2, 1). This can then be JOINed to the original table to get the data for latest date:
SELECT t1.id, t1.cid, t1.number, t1.value, t1.date
FROM data t1
JOIN (
SELECT LEAST(id, cid) AS l_id,
GREATEST(id, cid) AS g_id,
MAX(date) AS max_date
FROM data
GROUP BY l_id, g_id
) t2 ON t2.max_date = t1.date
AND (t2.l_id = t1.id AND t2.g_id = t1.cid OR
t2.l_id = t1.cid AND t2.g_id = t1.id)
Output (for your sample data):
id cid number value date
1 2 57 one to two 2020-04-19T11:27:02Z
9 2 58 nine to two 2020-04-19T11:28:01Z
Demo on SQLFiddle
I want to select distinct records in my database but I can't get it to work at all. I have tried DISTINCT and GROUP BY but still no luck.
Example:
This is my code:
SELECT
t1.room_id as Room_ID,
t1.room_name as Room_Name,
t2.price_date as Price_for_date,
t3.amount as Price ,
COUNT(t3.unit_id) as c
FROM
table1 AS t1
LEFT JOIN table3 AS t3 ON t1.room_id = t3.room_id
LEFT JOIN table2 AS t2 ON t3.price_room_id = t2.price_room_id
WHERE
t2.price_date BETWEEN (20180130) AND (20180530)
GROUP BY
t2.price_date,
t1.room_id
ORDER BY
t1.room_id,
t2.price_date DESC
T1:
id | room_id | room_name
-----------------------
1 | room1 | rm1
2 | room2 | rm2
3 | room3 | rm3
4 | room4 | rm4
5 | room5 | rm5
T2:
id | price_room_id | price_date
-------------------------------
1 | 000001 | 2018-01-30
2 | 000002 | 2018-02-30
3 | 000003 | 2018-03-30
4 | 000004 | 2018-04-30
5 | 000005 | 2018-05-30
T3:
id | room_id | price_room_id | amount
-------------------------------------
1 | room1 | 00001 | 100000
2 | room1 | 00002 | 101000
3 | room2 | 00002 | 110000
4 | room3 | 00003 | 200000
5 | room3 | 00004 | 300000
6 | room4 | 00001 | 100000
7 | room5 | 00005 | 350000
What I wanted is to select the room_id, price_room_id, and amount with its latest records between the given dates. From the table above I should get the following:
room_id | price_room_id | amount
-------------------------------------
room1 | 00002 | 101000
room2 | 00002 | 110000
room3 | 00004 | 200000
room4 | 00001 | 100000
room5 | 00005 | 350000
But what I'm getting is like this:
room_id | price_room_id | amount
-------------------------------------
room1 | 00002 | 101000
room1 | 00001 | 100000
room2 | 00002 | 110000
room3 | 00004 | 200000
room3 | 00003 | 110000
room4 | 00001 | 100000
room5 | 00005 | 350000
Try removing the Group by and put DISTINCT in SELECT. SELECT DISTINCT... because group by will group every room_id but in your case you just want to get the latest price_date.
SELECT DISTINCT (t1.room_id as Room_ID),
t1.room_name as Room_Name,
t2.price_room_id as Price_room_id,
t2.price_date as Price_for_date,
t3.amount as Price ,
COUNT(t3.unit_id) as c
FROM
table1 AS t1
LEFT JOIN table3 AS t3 ON t1.room_id = t3.room_id
LEFT JOIN table2 AS t2 ON t3.price_room_id = t2.price_room_id
WHERE
t2.price_date = max(t2.price_date)
ORDER BY
t1.room_id;
Unfortunately I don't have the reputation to comment but what #Caius Jard is saying is that each room_id has multiple price_room_ids which is reflected in the output you actually received. But the result that you want only has one price associated with each room_id so which price_room_id do you want to return for each room_id? From your comment, it seems like you want only the most recent price for each room? However, the initial query that you gave us also has some outputs that are not reflected with the example/desired output you gave. For example, COUNT(t3.unit_id) as c what do you want this output to be?
If you just want to show the latest price_date and COUNT(t3.unit_id) as c with only those latest prices you should probably filter by the latest price_date:
SELECT
t1.room_id as Room_ID,
t1.room_name as Room_Name,
t2.price_room_id as Price_room_id,
t2.price_date as Price_for_date,
t3.amount as Price ,
COUNT(t3.unit_id) as c
FROM
table1 AS t1
LEFT JOIN table3 AS t3 ON t1.room_id = t3.room_id
LEFT JOIN table2 AS t2 ON t3.price_room_id = t2.price_room_id
WHERE
t2.price_date = max(t2.price_date)
GROUP BY
t1.room_id
ORDER BY
t1.room_id;
EDIT:
Okay I think I understand now. I am not really sure how to get the max date from a date interval and I think this probably a super slow query but try this out:
SELECT
t1.room_id as Room_ID,
t1.room_name as Room_Name,
t2.price_room_id as Price_room_id,
t2.price_date as Price_for_date,
t3.amount as Price ,
COUNT(t3.unit_id) as c
FROM
table1 AS t1
LEFT JOIN table3 AS t3 ON t1.room_id = t3.room_id
LEFT JOIN table2 AS t2 ON t3.price_room_id = t2.price_room_id
WHERE
t2.price_date = (select max(t2.price_date) where t2.price_date BETWEEN '2018-01-30' AND '2018-05-30')
GROUP BY
t1.room_id
ORDER BY
t1.room_id;
In the lists of players I need to find find the maximum rating and current rating
Petr | 1 | 2016-12-01 00:00:00
Petr | 2 | 2016-12-02 00:00:00
Petr | 3 | 2016-12-03 00:00:00
Oleg | 3 | 2016-12-01 00:00:00
Oleg | 2 | 2016-12-02 00:00:00
Oleg | 1 | 2016-12-03 00:00:00
I want to get a Output:
name | min | current
Petr | 1 | 3
Oleg | 1 | 1
For to find the maximum, I try
SELECT t1.rank as min
FROM table t1
LEFT JOIN table t2
ON t1.name = t2.name AND t1.rank > t2.rank
WHERE t2.name IS NULL
And other solve, for find the current
SELECT t1.rank as current
FROM table t1
WHERE t1.dt=(SELECT MAX(dt) FROM table t2 WHERE t1.name = t2.name)
I think you are looking for the minimum rating not maximum.
To get current, the rating with max date, use GROUP BY and then join the original table again, to get the rating value for this max date:
SELECT
t1.Name,
MAX(t2.MinRating) AS MinRating,
MAX(t1.Rating) AS Current
FROM yourTable AS t1
INNER JOIN
(
SELECT Name, MIN(rating) AS MinRating, MAX(rateDate) AS MaxRateDate
FROM yourTable
GROUP BY Name
) AS t2 ON t1.Name = t2.Name AND t1.rateDate = t2.MaxRateDate
GROUP BY t1.Name;
fiddle demo
| Name | MinRating | Current |
|------|-----------|---------|
| Oleg | 1 | 1 |
| Petr | 1 | 3 |
I have 3 tables. I need to join those 3 and get 2 fields from each table. And there will be few where conditions. Where condition is for date range. Even if one table has the the result I need to show it along with other table data showing as 0.
I have tried using inner join. But what it does is taking only 1st where condition and if no result in first it will not go for next conditions. My table structures and required output are shown below.
table1
+--------+---------+------------+
| amount | site_id | date |
+--------+---------+------------+
| 10 | 1 | 12/12/2014 |
| 50 | 2 | 10/12/2014 |
| 30 | 3 | 05/11/2014 |
+--------+---------+------------+
table2
+--------+---------+------------+
| amount | site_id | date |
+--------+---------+------------+
| 100 | 1 | 2/11/2014 |
| 40 | 2 | 10/10/2014 |
| 30 | 3 | 05/11/2014 |
+--------+---------+------------+
table3
+--------+---------+------------+
| amount | site_id | date |
+--------+---------+------------+
| 60 | 1 | 12/12/2014 |
| 50 | 3 | 11/12/2014 |
| 70 | 4 | 05/09/2014 |
+--------+---------+------------+
output : total amounts between 01/12/2014 and 31/12/2014
+---------+---------------+---------------+---------------+-------+
| site_id | table1_amount | table2_amount | table3_amount | total |
+---------+---------------+---------------+---------------+-------+
| 1 | 60 | 0 | 60 | 120|
| 3 | 0 | 0 | 50 | 50 |
+---------+---------------+---------------+---------------+-------+
Can anyone suggest a query to get this output?
This is what I have done so far
select sum(table1.amount),sum(table2.amount),sum(table3.amount),(sum(table1.amount)+sum(table2.amount)+sum(table3.amount)) from table1 inner join table2 on table1.site_id=table2.site_id inner join table3 on table3.site_id=table2.site_id where table1.date>='01/12/2014' and table1.date<='31/12/2014' or table2.date>='01/12/2014' and table2.date<='31/12/2014' or table3.date>='01/12/2014' and table3.date<='31/12/2014' group by table1.site_id
Try this:
SELECT S.site_id,
IFNULL(t1.table1_Amount, 0) AS table1_Amount,
IFNULL(t2.table2_Amount, 0) AS table2_Amount,
IFNULL(t3.table3_Amount, 0) AS table3_Amount,
(IFNULL(t1.table1_Amount, 0) + IFNULL(t2.table2_Amount, 0) + IFNULL(t3.table3_Amount, 0)) AS total
FROM Site S
LEFT OUTER JOIN ( SELECT t1.site_id, SUM(t1.amount) AS table1_Amount
FROM table1 t1
WHERE t1.date >= '01/12/2014' AND t1.date <= '31/12/2014'
GROUP BY t1.site_id
) AS t1 ON S.site_id = t1.site_id
LEFT OUTER JOIN ( SELECT t2.site_id, SUM(t2.amount) AS table2_Amount
FROM table2 t2
WHERE t2.date >= '01/12/2014' AND t2.date <= '31/12/2014'
GROUP BY t2.site_id
) AS t2 ON S.site_id = t2.site_id
LEFT OUTER JOIN ( SELECT t3.site_id, SUM(t3.amount) AS table3_Amount
FROM table1 t3
WHERE t3.date >= '01/12/2014' AND t3.date <= '31/12/2014'
GROUP BY t3.site_id
) AS t3 ON S.site_id = t3.site_id;
I have prices in two different tables and want to subtract them (current price-last day price) and ORDER them in DESC form. I was wondering if it can be done using a single MySQL command.
Table Structure
Table 1
id | Item Name | Date | Price
1 | alpha | 2011-10-05 | 10
2 | beta | 2011-10-05 | 12
3 | gamma | 2011-10-05 | 14
Table 2
id | Item Name | Date | Price
1 | alpha | 2011-10-04 | 8
2 | beta | 2011-10-04 | 10
3 | gamma | 2011-10-04 | 12
4 | alpha | 2011-10-03 | 4
5 | beta | 2011-10-03 | 6
6 | gamma | 2011-10-03 | 8
SELECT
table1.id, table1.`Item Name`,
table1.`Date` AS CurrDate, table1.Price AS CurrPrice,
table2.`Date` AS PrevDate, table2.Price AS PrevPrice,
table1.Price - table2.Price AS Difference
FROM table1
LEFT JOIN table2 ON table1.id = table2.id AND table1.`Date` - INTERVAL 1 DAY = table2.`Date`
ORDER BY Difference DESC
There is nothing special about this query except the way I've used the LEFT JOIN. I believe if yesterday's rates for a record are not available, the the last three columns would contain NULL. Output:
id | Item Name | CurrDate | CurrPrice | PrevDate | PrevPrice | Difference
2 | beta | 2011-10-05 | 12 | 2011-10-04 | 10 | 2
3 | gamma | 2011-10-05 | 14 | 2011-10-04 | 12 | 2
1 | alpha | 2011-10-05 | 10 | 2011-10-04 | 8 | 2
SELECT
a.price as price1
, IFNULL(b.price,'(no data)') as price2
, (a.price - IFNULL(b.price,0)) as difference
FROM table1 a
LEFT JOIN table2 b ON (a.`item name` = b.`item name`)
GROUP BY a.`item name`
HAVING IFNULL(b.`date`,'') = MAX(IFNULL(b.`date`,'')
Here's how it works.
It selects data from 2 tables: All data from table1 and matching data from table2.
If it cannot find matching data from table2 it will substitute null values in place of the missing rows. (left join)
Then it groups (group by) rows together based on table1.item name.
This combines multiple rows per item.
The having clause fixes this by only selecting the newest date rows from table2.
A small correction is build into the select and having clauses to deal with the case when there is no data in table2 to match table1.
Your query should be:
SELECT
s.closing as price1
, IFNULL(sh.closing,'(no data)') as price2
, (s.closing - IFNULL(sh.closing,0)) as difference
FROM stocks s
LEFT JOIN stockhistory sh ON (s.symbol = sh.symbol)
GROUP BY s.symbol
HAVING IFNULL(sh.edate,'') = MAX(IFNULL(sh.edate,'')
LIMIT 30 OFFSET 0;