my table person like:
id, bron_year, file_date
2, 1943, 2010
5, 1952, 2017
7, 1953, 2018
8, 1952, 2018
9, 1954, 2017
Here the file_date means the file of person's create date, and file_date >= 2009.
And I create a procedure like:
CREATE OR REPLACE PROCEDURE `aged_person`()
BEGIN
DECLARE c_year int;
SET c_year = 2009;
WHILE c_year < YEAR(CURDATE()) DO
SELECT * FROM `person` WHERE YEAR(`file_date`) = c_year AND c_year - `bron_year` >= 65 ORDER BY `file_date` ASC, `id` ASC;
SET c_year = c_year + 1;
END WHILE;
END;
It means in every year, collect the aged person (in that year, person's age >= 65).
Now I want union all the results, and must keep the order. How to do that please?
BTW, I do not want create a temp table, because some person will be out (moving house, missing visit), then the person will not in table.
Example:
If c_year = 2018, the results (keep order):
2, 1943, 2010
5, 1952, 2017
8, 1952, 2018
7, 1953, 2018
If c_year = 2019, the results (keep order):
2, 1943, 2010
5, 1952, 2017
8, 1952, 2018
7, 1953, 2018
9, 1954, 2017
Simple query, and no stored procedures:
SELECT *
FROM person
WHERE file_date >= 2009
AND (file_date - bron_year) >= 65
ORDER BY file_date ASC, id ASC
Related
In table, data is in Timestamp format, but I shared it in Time(start_at), Time(end_at) format.
Table structure:
id, start_at, end_at
1, 03:00:00, 06:00:00
2, 02:00:00, 05:00:00
3, 01:00:00, 08:00:00
4, 08:00:00, 13:00:00
5, 09:00:00, 21:00:00
6, 13:00:00, 16:00:00
6, 15:00:00, 19:00:00
For result we need to count ids which were active in between the start_at, end_at time.
hours, count
0, 0
1, 1
2, 2
3, 3
4, 3
5, 2
6, 1
7, 1
8, 1
9, 2
10, 2
11, 2
12, 2
13, 3
14, 2
15, 3
16, 2
17, 2
18, 2
19, 1
20, 1
21, 0
22, 0
23, 0
Either
WITH RECURSIVE
cte AS (
SELECT 0 `hour`
UNION ALL
SELECT `hour` + 1 FROM cte WHERE `hour` < 23
)
SELECT cte.`hour`, COUNT(test.id) `count`
FROM cte
LEFT JOIN test ON cte.`hour` >= HOUR(test.start_at)
AND cte.`hour` < HOUR(test.end_at)
GROUP BY 1
ORDER BY 1;
or
WITH RECURSIVE
cte AS (
SELECT CAST('00:00:00' AS TIME) `hour`
UNION ALL
SELECT `hour` + INTERVAL 1 HOUR FROM cte WHERE `hour` < '23:00:00'
)
SELECT cte.`hour`, COUNT(test.id) `count`
FROM cte
LEFT JOIN test ON cte.`hour` >= test.start_at
AND cte.`hour` < test.end_at
GROUP BY 1
ORDER BY 1;
The 1st query returns hours column in time format whereas the 2nd one returns numeric value for this column. Select the variant which is safe for you.
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=5a77b6e3158be06c7a551cb7e64673de
There are two different tables, just need to subtract price between same month with same year, if no data just show zero for that particular month and year .Now, it just subtracting with row by row irrespective of month and year.
Table 1 Table2
Price tran_date Price post_date
60 2018-01-01 30 2018-01-15
40 2018-02-08 30 2018-02-02
50 2018-12-28 30 2018-11-01
40 2019-03-01 10 2019-01-08
80 2019-04-11 60 2019-04-29
40 2019-10-01
Expected Answer:
Sum(price). Year
30 January 2018
10 February 2018
30 November 2018
50 December 2018
-10 January 2019
40 March 2019
20 April 2019.
40 October 2019
Actual Answer:
Sum(Price) Year
30 January 2018
10 February 2018
10 December 2018
30 March 2019
20 April 2019
-40 October 2019
SQL Query for table1
Select sum(price) from table1 where date(tran_date)
between ‘2018-01-01’ and ‘2019-12-31’
group by month(tran_date),year(tran_date)
SQL Query for table2
Select sum(price) from table2 where date(post_date)
between ‘2018-01-01’ and ‘2019-12-31’
group by month(post_date),year(post_date)
It’s should not subtract from 1st row of table1 with 1st row of table2,it should subtract with same month with same year. If there is no data just show zero for that particular month and year.
Please do help.Thanks in Advance.
seems you want the absolute difference, try add abs()
sample
select date_year, date_month,
abs(sum(price))
from ((select date_year, date_month, price from
(values (60, '2018', '01'),
(40, '2018', '02'),
(50, '2018', '12'),
(40, '2019', '03'),
(80, '2019', '04') ) table1 (price, date_year, date_month)
) union all
(select date_year, date_month, - price from (
values (30, '2018', '01'),
(30, '2018', '02'),
(30, '2018', '11'),
(10, '2019', '01'),
(60, '2019', '04'),
(40, '2019', '10')
) table2 (price, date_year, date_month)
)
) t
group by date_year, date_month
order by date_year, date_month
see the fiddle
https://www.db-fiddle.com/f/qVQYB2KXSTbJNEkSH1oGuG/0
Is this what you want?
select year(dte), month(dte),
greatest( sum(price), 0)
from ((select tran_date as dte, price from table1
) union all
(select post_date, - price from table2
)
) t
group by year(dte), month(dte);
It seems very strange to not subtract the values. I suspect you might just want:
select year(dte), month(dte),
sum(price)
from ((select tran_date as dte, price from table1
) union all
(select post_date, - price from table2
)
) t
group by year(dte), month(dte)
I am not very familiar with sql however I have to do a query for a sale prediction.
The data is for the sale with distinct prodID, shopID, weekDay, date and Sale. I need to get the sale of the same product in the same shop and same weekDay in the past (e.g) 3 weeks. Therefore some proper pivoting is necessary. There might be that for some days there is no sale record for that product-shop-weekday combination. Also importantly I have to ignore negative sale values (if any) for average calculation.
This is header of the data:
DATE prodID shopID sale weekDay
2017-03-01 8 16 4.8 Wednesday
2017-03-01 2 16 18.8 Wednesday
2017-03-01 62 16 1.7 Wednesday
2017-03-01 34 16 3.6 Wednesday
2017-03-01 32 16 12.0 Wednesday
2017-03-02 8 16 3.6 Thursday
2017-03-02 34 16 15.8 Thursday
Ideal outcome is:
DATE prodID shopID sale weekDay saleWeek-1 saleWeek-2 saleWeek-3 ave_3sale
Perhaps a self-join can be used to build the new columns. Thank you very much much for your help.
I made you an sqlfiddle example to show you how you can make your sql statement
http://www.sqlfiddle.com/#!9/1877b3/4/0
You of course put in your tablename and columnnames.
the example would show you the sales of every day plus what you sold of that product for that salesID last week and that 2 weeks before.
CREATE TABLE salestable (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
datelit Date NOT NULL,
productID int(10) NOT NULL,
saleID int(10) NOT NULL,
sale float(4,2) NOT NULL,
weekday CHAR(30) NOT NULL,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
INSERT INTO `salestable` (`id`,`datelit`, `productID`, `saleID`,`sale`,`weekday`) VALUES
(NULL,'2019-05-18', 8, 16, 4.8, 'Wednesday'),
(NULL,'2019-05-18', 2, 16, 18.8, 'Wednesday'),
(NULL,'2019-05-18', 62, 16, 1.7, 'Wednesday'),
(NULL,'2019-05-18', 34, 16, 3.6, 'Wednesday'),
(NULL,'2019-05-17', 32, 16, 12.0, 'Wednesday'),
(NULL,'2019-05-18', 8, 16, 3.6, 'Wednesday'),
(NULL,'2019-05-18', 34, 16, 15.8, 'Wednesday');
SELECT a.datelit,a.productID, a.saleID, a.sale,a.weekday, b.salesumweek1, c.salesumweek2
FROM `salestable` a
Left JOIN (
SELECT saleID,productID, SUM(sale) as salesumweek1
FROM `salestable`
Where datelit BETWEEN DATE_ADD(CURDATE(), INTERVAL -7 DAY) AND CURDATE()
GROUP BY saleID,productID
) b ON a.saleID = b.saleID AND a.productID = b.productID
Left JOIN (
SELECT saleID,productID, SUM(sale) as salesumweek2
FROM `salestable`
Where datelit BETWEEN DATE_ADD(CURDATE(), INTERVAL -7 DAY) AND DATE_ADD(CURDATE(), INTERVAL -14 DAY)
GROUP BY saleID,productID
) c ON a.saleID = c.saleID AND a.productID = c.productID;
hi i have the following table, and I want to select the max(count(*)) of plugged for each month. sqlfiddle.com/#!2/13036/1
select * from broadcast
profile, plugged, company, tstamp
1, 2, 1, 2013-10-01 08:20:00
1, 3, 1, 2013-10-01 08:20:00
2, 1, 1, 2013-10-01 08:20:00
2, 3, 1, 2013-10-01 08:20:00
3, 1, 1, 2013-10-01 08:20:00
3, 1, 1, 2013-09-01 08:20:00
so if I do something like the following:
select plugged,
count(*),
extract(month from tstamp),
extract(year from tstamp)
from broadcast
where company=1
group by plugged,
extract(month from tstamp),
extract(year from tstamp)
order by count(*) desc;
output:
plugged, count(*), extract(month from tstamp), extract(year from tstamp)
3, 2, 10, 2013
1, 2, 10, 2013
2, 1, 10, 2013
1, 1, 9, 2013
desired output:
plugged, count(*), extract(month from tstamp), extract(year from tstamp)
3, 2, 10, 2013
1, 2, 10, 2013
1, 1, 9, 2013
which is right... but I only want the max(count(*)) (for example first row only in this case). There may be scenarios where there are 2 rows with the max count, but for each MONTH/YEAR i only want to return the max count row(s)...do I need an inner select statement or something?
try this
select plugged, max(counts) counts, month , year
from
(select plugged ,count(*) as counts ,extract(month from tstamp) month , extract(year from tstamp) year from broadcast where company=1
group by plugged,month ,year order by counts desc ) as x ;
I have a table with two Date columns. DATE1 is sometimes NULL and sometimes contains duplicate values. DATE2 is always populated and unique. My table is sorted by latest DATE2 date.
I'd like to create a new date column where DATE1 will be selected unless its value is duplicated from the next row or it's NULL. In this case, I want to take the value of DATE2. I also need two boolean columns that tell me when either of those conditions were met. Let me demonstrate using an example so it's clearer.
In the table below, row 5 and 6 have a value of Jul 27, 2011 so I'd like to set the new date column of row 5 to Aug 4, 2011 (which is DATE2). In row 3, the value of DATE1 is NULL so I want to take the value of DATE2.
I've tried a few inner select statements but can't get this to work. Any ideas?
My table as it currently stands in the database:
Row DATE1 DATE2
--------------------------------------
1 Oct 10, 2011 Nov 13, 2011
2 Oct 10, 2011 Oct 10, 2011
3 NULL Oct 8, 2011
4 Aug 12, 2011 Aug 12, 2011
5 Jul 27, 2011 Aug 4, 2011
6 Jul 27, 2011 Jul 28, 2011
7 Jul 1, 2011 Jul 26, 2011
8 May 24, 2011 Jun 13, 2011
What I expect the final result to look like:
Row FINAL_DATE DATE1_DUPLICATE DATE1_WAS_NULL
----------------------------------------------------------
1 Nov 13, 2011 TRUE FALSE
2 Oct 10, 2011 FALSE FALSE
3 Oct 8, 2011 FALSE TRUE
4 Aug 12, 2011 FALSE FALSE
5 Aug 4, 2011 TRUE FALSE
6 Jul 27, 2011 FALSE FALSE
7 Jul 1, 2011 FALSE FALSE
8 May 24, 2011 FALSE FALSE
Thanks so much!
This can be handled with sequential scanning of the table and using MySQL variables. You can test in (updated) SQL-fiddle:
SELECT date2
, dd
, DATE_FORMAT(dd, '%b %e, %Y') AS final_date
, date1_duplicate
, date1_was_null
FROM
( SELECT date2
, COALESCE( (date1 = #d OR date1 = #prev), FALSE)
AS date1_duplicate
, (date1 IS NULL) AS date1_was_null
, #d := CASE WHEN (date1 = #d OR date1 = #prev)
THEN date2
ELSE COALESCE(date1, date2)
END AS dd
, #prev := date1 AS pre
FROM tableX AS t
CROSS JOIN
( SELECT #d := DATE('1000-01-01')
, #prev := #d
) AS dummy
ORDER BY date2 ASC
) AS tmp
ORDER BY date2 DESC
;