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;
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 search TABLE1 and count which number_id has the most 5's in experience column.
TABLE1
+-------------+------------+
| number_id | experience |
+-------------+------------+
| 20 | 5 |
| 20 | 5 |
| 19 | 1 |
| 18 | 2 |
| 15 | 3 |
| 13 | 1 |
| 10 | 5 |
+-------------+------------+
So in this case it would be number_id=20
Then do an inner join on TABLE2 and map the number that matches the number_id in TABLE1.
TABLE2
+-------------+------------+
| id | number |
+-------------+------------+
| 20 | 000000000 |
| 29 | 012345678 |
| 19 | 123456789 |
| 18 | 223456789 |
| 15 | 345678910 |
| 13 | 123457898 |
| 10 | 545678910 |
+-------------+------------+
So the result would be:
000000000 (2 results of 5)
545678910 (1 result of 5)
So far I have:
SELECT number, experience, number_id, COUNT(*) AS SUM FROM TABLE1
INNER JOIN TABLE2 ON TABLE1.number_id = TABLE2.id
WHERE experience = '5' order by SUM LIMIT 10
But it's returning just
545678910
How can I get it to return both results and by order of number of instances of 5 in the experience column?
Thanks
This query will give you the results that you want. The subquery fetches all the number_id that have experience values of 5. The SUM(experience=5) works because MySQL uses a value of 1 for true and 0 for false. The results of the subquery are then joined to table2 to give the number field. Finally the results are ordered by the number of experience=5:
SELECT t2.number, t1.num_fives
FROM (SELECT number_id, SUM(experience = 5) AS num_fives
FROM table1
WHERE experience = 5
GROUP BY number_id) t1
JOIN table2 t2
ON t2.id = t1.number_id
ORDER BY num_fives DESC
Output:
number num_fives
000000000 2
545678910 1
SQLFiddle Demo
Add a group by clause:
SELECT number, experience, number_id, COUNT(*) AS SUM
FROM TABLE1
JOIN TABLE2 ON TABLE1.number_id = TABLE2.id
WHERE experience = '5'
GROUP BY 1, 2, 3 -- <<< Added this clause
ORDER BY SUM
LIMIT 10
Need help in Building a Query which can select a Item and sum up its QTY which is in 2 different Tables.
Example Scenario:
Table 1:
ID | ITEM_NAME | QTY |
1 | Item_Desc1 | 0 |
2 | Item_Desc2 | 2 |
3 | Item_Desc3 | 4 |
4 | Item_Desc4 | 0 |
Table 2:
ID | ITEM_ID | BATCHNO | QTY
1 | 1 | B1 | 100
2 | 1 | B2 | 100
3 | 2 | B3 | 0
4 | 3 | B2 | 100
5 | 4 | B2 | 200
6 | 4 | B3 | 100
Need a Query to show in a Data grid Table as follows:
ID | Item_Name | QTY
1 | Item_Desc1 | 200
2 | Item_Desc2 | 2
3 | Item_Desc3 | 104
4 | Item_Desc4 | 300
Note:
This Query should be useful to run a Search query using 'LIKE' operator by using which User can search for Items Needed
SAMPLE Image of My APPLICATION to Run Search query using Table 1 and Table 2
SAMPLE Image of My APPLICATION DATABASE - TABLE2
SAMPLE Image of My APPLICATION DATABASE - TABLE1
To get sum from 2 table you can use following query
select a.ID, a.ITEM_NAME, a.QTY + coalesce(b.QTY,0)
from Table1 a
left join (
select ITEM_ID,sum(QTY) QTY
from Table2
group by ITEM_ID
) b on a.ID = b.ITEM_ID
Demo
Try the following query
select tbl1.id as ID,tbl1.Item_Name, tbl.qty+sum(tbl2.qty) as QTY
from table1 as tbl1 JOIN table2 as tbl2
ON tbl1.id = tbl2.id group by tbl2.item_id
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
I have a table with columns start_date and end_date. What we need to do is Select everything and group them by date conflicts for each Object_ID.
A date conflict is when a row's start date and/or end date pass through another rows'. For instance, here are some examples of conflicts:
Row 1 has dates 1st through the 5th, Row 2 has dates 2nd through the 3rd.
Row 1 has dates 2nd through the 5th, Row 2 has dates 1st through the 3rd.
Row 1 has dates 2nd through the 5th, Row 2 has dates 3rd through the 6th.
Row 1 has dates 2nd through the 5th, Row 2 has dates 1st through the 7th.
So for example, if we have some sample data (assume the numbers are just days of the month for simplicity):
id | object_id | start_date | end_date
1 | 1 | 1 | 5
2 | 1 | 2 | 4
3 | 1 | 6 | 8
4 | 2 | 2 | 3
What i would expect to see is this:
object_id | start_date | end_date | numconflicts
1 | <na> | <na> | 2
1 | 6 | 8 | 0 or null
2 | 2 | 3 | 0 or null
And for a Second Test Case, Here is some sample data:
id | object_id | start_date | end_date
1 | 1 | 1 | 5
2 | 1 | 2 | 4
3 | 1 | 6 | 8
4 | 2 | 2 | 3
5 | 2 | 4 | 5
6 | 1 | 2 | 3
7 | 1 | 10 | 12
8 | 1 | 11 | 13
And for the second Test Case, what I would expect to see as output:
object_id | start_date | end_date | numconflicts
1 | <na> | <na> | 3
1 | 6 | 8 | 0 or null
2 | 2 | 3 | 0 or null
2 | 4 | 5 | 0 or null
1 | <na> | <na> | 2
Yes, I will need some way of differentiating the first and the second grouping (the first and last rows) but I haven't quite figured that out. The goal is to view this list, and then when you click on a group of conflicts you can view all of the conflicts in that group.
My first thought was to attempt some GROUP BY CASE ... clause but I just wrapped by head around itself.
The language I am using to call mysql is php. So if someone knows of a php-loop solution rather than a large mysql query i am all ears.
Thanks in advance.
Edit: Added in primary Keys to provide a little less confusion.
Edit: Added in a Test case 2 to provide some more reasoning.
This query finds the number of duplicates:
select od1.object_id, od1.start_date, od1.end_date, sum(od2.id is not null) as dups
from object_date od1
left join object_date od2
on od2.object_id = od1.object_id
and od2.end_date >= od1.start_date
and od2.start_date <= od1.end_date
and od2.id != od1.id
group by 1,2,3;
You can use this query as the basis of a query that gives you exactly what you asked for (see below for output).
select
object_id,
case dups when 0 then start_date else '<na>' end as start_date,
case dups when 0 then end_date else '<na>' end as end_date,
sum(dups) as dups
from (
select od1.object_id, od1.start_date, od1.end_date, sum(od2.id is not null) as dups
from object_date od1
left join object_date od2
on od2.object_id = od1.object_id
and od2.end_date >= od1.start_date
and od2.start_date <= od1.end_date
and od2.id != od1.id
group by 1,2,3) x
group by 1,2,3;
Note that I have used an id column to distinguish the rows. However, you could replace the test of id's not matching with comparisons on every column, ie replace od2.id != od1.id with tests that every other column is not equal, but that would require a unique index on all the other columns to make sense, and having an id column is a good idea anyway.
Here's a test using your data:
create table object_date (
id int primary key auto_increment,
object_id int,
start_date int,
end_date int
);
insert into object_date (object_id, start_date, end_date)
values (1,1,5),(1,2,4),(1,6,8),(2,2,3);
Output of first query when run against this sample data:
+-----------+------------+----------+------+
| object_id | start_date | end_date | dups |
+-----------+------------+----------+------+
| 1 | 1 | 5 | 1 |
| 1 | 2 | 4 | 1 |
| 1 | 6 | 8 | 0 |
| 2 | 2 | 3 | 0 |
+-----------+------------+----------+------+
Output of second query when run against this sample data:
+-----------+------------+----------+------+
| object_id | start_date | end_date | dups |
+-----------+------------+----------+------+
| 1 | 6 | 8 | 0 |
| 1 | <na> | <na> | 2 |
| 2 | 2 | 3 | 0 |
+-----------+------------+----------+------+
Oracle : This could be done with a subquery in a group by CASE statement.
https://forums.oracle.com/forums/thread.jspa?threadID=2131172
Mysql : You could have a view which had all the conflicts .
select distinct a1.appt, a2.appt from appointment a1, appointment a2 where a1.start < a2.end and a1.end > a2.start.
and then simply do a count(*) on that table.
Something like the following should work:
select T1.object_id, T1.start_date, T1.end_date, count(T1.object_id) as numconflicts
from T1
inner join T2 on T1.start_date between T2.start_date and T2.end_date
inner join T3 on T1.end_date between T2.start_date and T2.end_date
group by T1.object_id
I might be off a little bit, but it should help you get started.
Edit: Indented it properly