No results from SQL Query - mysql

I am trying to count the number of nights guests stay within a range. So less than 7 nights, between 7 and 14 nights and lastly more than 14 nights.
I would like the output to look something like this:
Range | Count
----------------------
<= 7 Nights | 3
8 - 14 Nights | 2
15 Nights + | 1
I am using MYSQL and have attempted the following two solutions, but no results seem to ever appear.
SELECT
CASE
WHEN booking_num_nights <= 7 THEN '<= 7 Nights'
WHEN booking_num_nights > 7 and booking_num_nights <= 14 THEN '8 - 14 Nights'
WHEN booking_num_nights > 14 THEN '15 Nights +'
END AS range, count(*) AS count_num
FROM BOOKING
WHERE booking_property_id = :id
GROUP BY range
The other attempt was as follows:
SELECT booking_num_nights as range, count(*) as count_num
FROM (SELECT
CASE
WHEN booking_num_nights <= 7 THEN '<= 7 Nights'
WHEN booking_num_nights > 7 and booking_num_nights <= 14 THEN '8 - 14 Nights'
WHEN booking_num_nights > 14 THEN '15 Nights +'
END AS range
FROM BOOKING)
WHERE booking_property_id = :id
GROUP BY range

range is a reserved word. Either use a different name or escape it:
SELECT
CASE
WHEN booking_num_nights <= 7 THEN '<= 7 Nights'
WHEN booking_num_nights > 7 and booking_num_nights <= 14 THEN '8 - 14 Nights'
WHEN booking_num_nights > 14 THEN '15 Nights +'
END AS `range`, count(*) AS count_num
FROM BOOKING
WHERE booking_property_id = :id
GROUP BY `range`
DEMO

Related

Convert Month into weeks in MySQL

I am looking to breakdown a Month into weeks(starting Monday) in MySQL.
For example,
Sept 3 - 9th
Sept 10 - 16th
How to achieve this using MySql?
Thanks in advance.
This query will produce the results you want. It generates a table of possible week numbers in the month (0 to 4) using a UNION, and then it adds those week numbers to the computation of the first Monday of the month (stored in the variable #firstday which is JOINed to the table of week numbers).
SELECT #firstday + INTERVAL w WEEK AS start, #firstday + INTERVAL w WEEK + INTERVAL 6 DAY AS end
FROM (SELECT 0 AS w UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) weeks
JOIN (SELECT #firstday := FROM_DAYS(TO_DAYS(CURDATE())-DAY(CURDATE())+1) +
(7 - WEEKDAY(FROM_DAYS(TO_DAYS(CURDATE())-DAY(CURDATE())+1))) % 7) f
HAVING end <= LAST_DAY(#firstday)
Output:
start end
2018-09-03 2018-09-09
2018-09-10 2018-09-16
2018-09-17 2018-09-23
2018-09-24 2018-09-30
To run the query for any given month, replace CURDATE() in the computation of #firstday (4 places) with a date in the month you are interested in e.g.
SELECT #firstday + INTERVAL w WEEK AS start, #firstday + INTERVAL w WEEK + INTERVAL 6 DAY AS end
FROM (SELECT 0 AS w UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) weeks
JOIN (SELECT #firstday := FROM_DAYS(TO_DAYS('2018-01-20')-DAY('2018-01-20')+1) +
(7 - WEEKDAY(FROM_DAYS(TO_DAYS('2018-01-20')-DAY('2018-01-20')+1))) % 7) f
HAVING end <= LAST_DAY(#firstday)
Output:
start end
2018-01-01 2018-01-07
2018-01-08 2018-01-14
2018-01-15 2018-01-21
2018-01-22 2018-01-28
If you have the flexibility of setting variables, you can clean up the query like so:
SET #day = '2018-01-20';
SET #firstday := FROM_DAYS(TO_DAYS(#day)-DAY(#day)+1) + (7 - WEEKDAY(FROM_DAYS(TO_DAYS(#day)-DAY(#day)+1))) % 7;
SELECT #firstday + INTERVAL w WEEK AS start, #firstday + INTERVAL w WEEK + INTERVAL 6 DAY AS end
FROM (SELECT 0 AS w UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) weeks
HAVING end <= LAST_DAY(#firstday)
You can use function week(date) - https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_week

Select date interval inside WHERE clause

I'm trying to query a list of loans that have been opened within the past 36 months. I'm also trying to query a count of loans that have been opened within the past 12 months as a separate column.
The query is returning the same values for both columns, how can I get get the count from both 36 month and 12 month intervals without running a separate query?
SELECT
`XDL-NAME`,
COUNT(distinct`XLN-LOANDATE`) as '36 Month Count',
COUNT(IF(`XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 12 MONTH), 1 , NULL)) AS '12 Month Count'
from
LOAN
JOIN
DEALER ON `XLN-DLNO` = `XDL-NUM` WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 36 MONTH)
GROUP BY `XDL-NAME`
Instead of count for 12 months, change to sum like below
SELECT
`XDL-NAME`,
COUNT(distinct`XLN-LOANDATE`) as '36 Month Count',
SUM(IF(`XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 12 MONTH), 1 , 0)) AS '12 Month Count'
from
LOAN
JOIN
DEALER ON `XLN-DLNO` = `XDL-NUM` WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 36 MONTH)
GROUP BY `XDL-NAME`
Try this:
SELECT
`XDL-NAME`,
count((SELECT `XLN-LOANDATE` WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 36 MONTH))) AS '36 Month Count',
count((SELECT `XLN-LOANDATE` WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 12 MONTH))) AS '12 Month Count',
from
LOAN
JOIN
DEALER ON `XLN-DLNO` = `XDL-NUM`
GROUP BY `XDL-NAME`
What I did was use subqueries to count each interval you wanted. This way they should output with Name, 36 month count, 12 month count all on one line (record).
I would expect this query to return the two separate counts:
SELECT `XDL-NAME`,
COUNT(*) as `36 Month Count`,
SUM(`XLN-LOANDATE` >= DATE_SUB(NOW(), INTERVAL 12 MONTH)) AS `12 Month Count`
FROM loan l join
dealer d
ON `XLN-DLNO` = `XDL-NUM`
WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(), INTERVAL 36 MONTH)
GROUP BY `XDL-NAME`;
Try SUM like:
SUM(IF('2016-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0)) AS '12 Month Count'
Sample
mysql> SELECT IF('2016-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0);
+----------------------------------------------------+
| IF('2016-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0) |
+----------------------------------------------------+
| 1 |
+----------------------------------------------------+
1 row in set (0,00 sec)
mysql> SELECT IF('2015-12-22' >= NOW() -INTERVAL 12 MONTH, 1, 0);
+----------------------------------------------------+
| IF('2015-12-22' >= NOW() -INTERVAL 12 MONTH, 1, 0) |
+----------------------------------------------------+
| 1 |
+----------------------------------------------------+
1 row in set (0,00 sec)
mysql> SELECT IF('2015-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0);
+----------------------------------------------------+
| IF('2015-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0) |
+----------------------------------------------------+
| 0 |
+----------------------------------------------------+
1 row in set (0,00 sec)
mysql>

MySQL SELECT Query: Add 28 days to the last date of a financial quarter

I am wanting to add 28 days to the last day of a quarter.
I currently have the following to determine the Quarter period, how can I then add 28 days to the last date of the last month in the quarter.
CASE -- Results: 2011-Q4 (Financial Year-Qtr)
WHEN MONTH(T5.date_purchased) BETWEEN 1 AND 3 THEN concat((YEAR(T5.date_purchased) - 1), '-', 'Q3')
WHEN MONTH(T5.date_purchased) BETWEEN 4 AND 6 THEN concat((YEAR(T5.date_purchased) - 1), '-', 'Q4')
WHEN MONTH(T5.date_purchased) BETWEEN 7 AND 9 THEN concat((YEAR(T5.date_purchased) - 0), '-', 'Q1')
WHEN MONTH(T5.date_purchased) BETWEEN 10 AND 12 THEN concat((YEAR(T5.date_purchased) - 0), '-', 'Q2')
END AS FYrQtr,
I do not need to account for anything unusual, simply the 28th of the next month in the next quarter.
I have tried the following, but of course that adds 28 days to the order date, not the financial qtr. (I do not need the time)
CASE -- Results: 2012-06-20 07:20:07 not 2012-07-28
WHEN MONTH(T5.date_purchased) BETWEEN 1 AND 3 THEN date_add(T5.date_purchased, Interval 28 day)
WHEN MONTH(T5.date_purchased) BETWEEN 4 AND 6 THEN date_add(T5.date_purchased, Interval 28 day)
WHEN MONTH(T5.date_purchased) BETWEEN 7 AND 9 THEN date_add(T5.date_purchased, Interval 28 day)
WHEN MONTH(T5.date_purchased) BETWEEN 10 AND 12 THEN date_add(T5.date_purchased, Interval 28 day)
END AS FRangeQtrBAS,
Many thanks in advance.
Get the year from the purchasedate and concat it with the know end of quarter month and day:
CASE
WHEN MONTH(T5.date_purchased) BETWEEN 1 AND 3 THEN date_add(CONCAT(YEAR(T5.date_purchased), '-03-31'), Interval 28 day)
WHEN MONTH(T5.date_purchased) BETWEEN 4 AND 6 THEN date_add(CONCAT(YEAR(T5.date_purchased), '-06-30'), Interval 28 day)
WHEN MONTH(T5.date_purchased) BETWEEN 7 AND 9 THEN date_add(CONCAT(YEAR(T5.date_purchased), '-09-30'), Interval 28 day)
WHEN MONTH(T5.date_purchased) BETWEEN 10 AND 12 THEN date_add(CONCAT(YEAR(T5.date_purchased), '-12-31'), Interval 28 day)
END AS FRangeQtrBAS

Percentage change from previous row when multiple rows have the same date?

I have a query that calculates ratios and returns them for each hour and server on a given day:
SELECT a.day,
a.hour,
Sum(a.gemspurchased),
Sum(b.gems),
Sum(b.shadowgems),
( Sum(b.gems) / Sum(a.gemspurchased) ) AS GemRatio,
( Sum(b.shadowgems) / Sum(a.gemspurchased) ) AS ShadowGemRatio
FROM (SELECT Date(Date_sub(createddate, INTERVAL 7 hour)) AS day,
Hour(Date_sub(createddate, INTERVAL 7 hour)) AS hour,
serverid,
Sum(gems) AS GemsPurchased
FROM dollartransactions
WHERE Date(Date_sub(createddate, INTERVAL 7 hour)) BETWEEN
Curdate() - INTERVAL 14 day AND Curdate()
GROUP BY 1,
2,
3) a,
/*Gems recorded from DollarTransactions Table after purchasing gem package*/
(SELECT Date(Date_sub(createddate, INTERVAL 7 hour)) AS day,
Hour(Date_sub(createddate, INTERVAL 7 hour)) AS hour,
serverid,
Sum(acceptedamount) AS Gems,
Sum(acceptedshadowamount) AS ShadowGems
FROM gemtransactions
WHERE Date(Date_sub(createddate, INTERVAL 7 hour)) BETWEEN
Curdate() - INTERVAL 14 day AND Curdate()
AND transactiontype IN ( 990, 2 )
AND fullfilled = 1
AND gemtransactionid >= 130000000
GROUP BY 1,
2,
3) b
/*Gems & Shadow Gems spent, recorded from GemTransactions Table */
WHERE a.day = b.day
AND a.serverid = b.serverid
GROUP BY 1,
2
This code returns the component parts of the ratios, as well as the ratios themselves (which are sometimes null):
day hour sum(a.GemsPurchased) sum(b.Gems) sum(b.ShadowGems) GemRatio ShadowGemRatio
9/5/2014 0 472875 465499 60766 0.9844 0.1285
9/5/2014 1 350960 371092 45408 1.0574 0.1294
9/5/2014 2 472985 509618 58329 1.0775 0.1233
9/5/2014 3 1023905 629310 71017 0.6146 0.0694
9/5/2014 4 1273170 628697 74896 0.4938 0.0588
9/5/2014 5 998920 637709 64145 0.6384 0.0642
9/5/2014 6 876470 651451 68977 0.7433 0.0787
9/5/2014 7 669100 667217 81599 0.9972 0.122
What I'd like to do is create an 8th and 9th column which calculate the % change from previous row for both GemRatio and ShadowGemRatio. I've seen other threads here on how to do this for specific queries, but I couldn't get it to work for my particular MySQL query...
Ok first create a view for that query. Let's call it v1:
CREATE VIEW v1 AS SELECT YOUR QUERY HERE;
Now here is the query to have the ratios. I assumed a day has 24 hours. The first row ratio change will be zero.
select now.*,
CASE
WHEN yesterday.gemRatio is null THEN 0
ELSE 100*(now.gemRatio-yesterday.gemRatio)/yesterday.gemRatio
END as gemChange,
CASE
WHEN yesterday.ShadowGemRatio is null THEN 0
ELSE 100*(now.ShadowGemRatio-yesterday.ShadowGemRatio)/yesterday.ShadowGemRatio
END as shadowGemChange
from v1 now left outer join v1 yesterday on
((now.day = yesterday.day && now.hour = yesterday.hour+1) ||
(DATEDIFF(now.day,yesterday.day) = 1 && now.hour = 0 && yesterday.hour=23))

date : group by month from day 2 to day 1 next month

I have query like this :
SELECT EXTRACT(MONTH FROM d.mydate) AS synmonth, SUM(apcp) AS apcptot
FROM t_synop_data2 d
WHERE d.mydate
BETWEEN '2011-01-01' AND '2011-12-31'
AND d.idx_synop = '06712'
GROUP BY synmonth
This query adds all rain (apcp) in a month like this :
1 32.8 => from 2011.01.01 to 2011.01.31
2 27.2 => from 2011.02.01 to 2011.02.28
3 21.0
4 21.8
5 88.5
6 131.4
7 118.6
8 57.1
9 80.9
10 84.6
11 1.1
12 143.5 => from 2011.12.01 to 2011.12.31
That's what I want, but with a little difference.
This difference is that i have to adds apcp from day 2 in the month to day 1 next month and then return a result like above.
1 132.8 => from 2011.01.02 to 2011.02.01
2 27.2 => from 2011.02.02 to 2011.03.01
3 21.0
4 21.8
5 88.5
6 131.4
7 118.6
8 57.1
9 80.9
10 84.6
11 1.1
12 143.5 => from 2011.12.02 to 2012.01.01
I tried something with add_date(), extract() or date_format() but without result.
Thank you for your answer
Vince
Here is the query :
SELECT EXTRACT(MONTH FROM ADDDATE(d.mydate,-1) ) AS synmonth
, SUM(apcp) AS apcptot
FROM t_synop_data2 AS d
WHERE ADDDATE(d.mydate,-1) BETWEEN '2011-01-01' AND '2012-12-31'
AND d.idx_synop = '06712'
GROUP BY synmonth
You can check the result by adding two columns like this:
SELECT EXTRACT(MONTH FROM ADDDATE(d.mydate,-1) ) AS synmonth
, SUM(apcp) AS apcptot
, MIN(d.mydate) AS date_min
, MAX(d.mydate) AS date_max
FROM t_synop_data2 AS d
WHERE ADDDATE(d.mydate,-1) BETWEEN '2011-01-01' AND '2012-12-31'
AND d.idx_synop = '06712'
GROUP BY synmonth
You can group by EXTRACT(MONTH FROM d.mydate - INTERVAL 1 DAY)
SELECT EXTRACT(MONTH FROM d.mydate) AS synmonth, SUM(apcp) AS apcptot
FROM t_synop_data2 d
WHERE d.mydate
BETWEEN '2011-01-01' AND '2011-12-31'
AND d.idx_synop = '06712'
GROUP BY EXTRACT(MONTH FROM d.mydate - INTERVAL 1 DAY)