Mysql Count with DAYOFWEEK AND BETWEEN not working together - mysql

I am trying to count a value where I get the count from the weekday and from the first 3 months of the year.
SELECT
SUM(count_LP) AS down1
FROM
`splittest`
WHERE DAYOFWEEK(DATE) = 2
AND (
dato BETWEEN 2014-01-01
AND 2014-04-01
)
It stops working when I add the BETWEEN.
Any ideas?

To specify dates you have to quote them like '2014-01-01'
SELECT
SUM(count_LP) AS down1
FROM
`splittest`
WHERE DAYOFWEEK(DATE) = 2
AND (
dato BETWEEN '2014-01-01'
AND '2014-04-01'
)

Related

MySQL_Retrieving stock price based on max and min_date

I am trying to retrieve closed and opened stock prices from the first and last date per month.
For some reason, the output of the 'end_date_closed_stock_price' is NULL.
Do you know any idea why it is giving this result?
Also, could you tell me the appropriate queries to retrieve the last date of the month?
The followings are my queries and output.
Thanks in advance!
SELECT YEAR(date) AS years
, MONTH(date) AS months
, CASE WHEN date = MAX(date) THEN close END end_date_closed_stock_price
, CASE WHEN date = MIN(date) THEN open END first_date_opened_stock_price
FROM nasdaq_feb_25_1971_feb_25_2021
GROUP
BY 1,2
ORDER
BY 1 DESC;
---OUTPUT---
2020 5 NULL 9382.349609
2019 1 NULL 6947.459961
2019 2 NULL 7266.279785
2019 3 NULL 7582.290039
There is probably a more efficient solution, but this should work:
WITH dates as
(SELECT YEAR(date) as years
,MONTH(date) AS months
,MAX(date) as end_date
,MIN(date) as first_date
FROM nasdaq_feb_25_1971_feb_25_2021
GROUP BY 1, 2)
SELECT dates.years
, dates.months
, price1.close as end_date_closed_stock_price
, price2.open as first_date_opened_stock_price
FROM dates
JOIN nasdaq_feb_25_1971_feb_25_2021 price1
ON price1.date = dates.end_date
JOIN nasdaq_feb_25_1971_feb_25_2021 price2
ON price2.date = dates.first_date
ORDER
BY 1 DESC, 2 DESC;

Aggregating table data in MySQL, is there an easier way to do this?

I'm trying to write a query that aggregates data from a table.
Essentially I have a long list of devices that have been inventoried and eventually installed over the last couple of years.
I want to find the average amount of time between when the device was received and when it was installed, and then have that data sorted by the month the device was installed. BUT in each month's row, I also want to include the data from the previous months.
So essentially what I want to see is: (sorry for terrible formatting)
MonthInstalled | TimeToInstall | Total#Devices
-----------------+---------------+----------------------------
Jan | 10 Days | 5
Feb(=Jan+Feb) | 15 Days | 18 (5 in Jan + 13 in Feb)
Mar(=Jan+Feb+Mar)| 13 Days | 25 (5 + 13 + 7)
...
The query I currently have written looks like this:
INSERT INTO DevicesInstall
SELECT ROUND(AVG(DATEDIFF(dvc.dt_install , dvc.dt_receive)), 1) AS 'Install',
COUNT(dvc.dvc_model) AS 'Total Devices',
MAX(dvc.dt_install) AS 'Date',
loc.loc_campus AS 'Campus'
FROM dvc_info dvc, location loc
WHERE dvc.dvc_loc_bin = loc.loc_bin
AND dvc.dt_install < '20160201'
;
Although this is functional, I have to iterate this for each month manually, so it is not scale-able. Is there a way to condense this at all?
We can return the dates using an inline view (derived table), and then join to the dvc_info table, so we can get the "cumulative" results.
To get the results for:
Jan
Jan+Feb
Jan+Feb+Mar
We need to return three copies of the rows for Jan, and two copies of the rows for Feb, and then collapse the those rows into an appropriate group.
The loc_campus is being included in the SELECT list... not clear why that is needed. If we want results "by campus", then we need to include that expression in the GROUP BY clause. Otherwise, the value returned for that non-aggregate is indeterminate... we will get a value for some row "in the group", but it could be any row.
Something like this:
SELECT d.dt AS `before_date`
, loc.loc_campus AS `Campus`
, ROUND(AVG(DATEDIFF(dvc.dt_install,dvc.dt_receive)),1) AS `Install`
, COUNT(dvc.dvc_model) AS `Total Devices`
, MAX(dvc.dt_install) AS `latest_dt_install`
FROM ( SELECT '2016-01-01' + INTERVAL 1 MONTH AS dt
UNION ALL SELECT '2016-01-01' + INTERVAL 2 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 3 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 4 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 5 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 6 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 7 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 8 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 9 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 10 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 11 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 12 MONTH
) d
CROSS
JOIN location loc
LEFT
JOIN dvc_info dvc
ON dvc.dvc_loc_bin = loc.loc_bin
AND dvc.dt_install < d.dt
GROUP
BY d.dt
, loc.loc_campus
ORDER
BY d.dt
, loc.loc_campus
Note that the value returned for d.dt will be the "up until" date. We're going to get '2016-02-01' returned for the January results. If we want to return a value of January date, we can use an expression in the SELECT list...
SELECT DATE_FORMAT(d.dt + INTERVAL -1 MONTH,'%Y-%m') AS `month`
Lots of options on query alternatives.
But it looks like the "big hump" is that to get cumulative results, we need to return multiple copies of the dvc_info rows, so the rows can be collapsed into each "grouping".
I recommend working on just the SELECT first. And get that tested working, before monkeying around to turn it into an INSERT ... SELECT.
FOLLOWUP
We can use any query as an inline view (derived table d) that returns a set of dates we want.
e.g.
FROM ( SELECT DATE_FORMAT(m.install_dt,'%Y-%m-01') + INTERVAL 1 MONTH AS dt
FROM dvc_install m
WHERE m.install_dt >= '2016-01-01'
GROUP BY DATE_FORMAT(m.install_dt,'%Y-%m-01') + INTERVAL 1 MONTH
) d
Note that with this approach, if there are no install_dt in February, we won't get back a row for February. Using the static UNION ALL SELECT approach allows us to get back "zero" counts, i.e. to return rows for months where there isn't an install_dt in that month. (But that's the answer to a different question... how do I get back a "zero" count for February when there aren't any rows for Februrary?)
Alternatively, if we have a calendar table e.g. cal that contains a list of the dates we want, we could just reference the table in place of the inline view, or the inline view query could get rows from that.
FROM ( SELECT cal.dt
FROM cal cal
WHERE cal.dt >= '2016-01-01'
AND cal.dt <= NOW()
AND DATE_FORMAT(cal.dt,'%d') = '01'
) d

How do I create MySQL query to get result from different year?

This is my original query:
SELECT *
FROM c60_hrd.hrclhf
WHERE hrch_clm_mth >= '1' AND hrch_clm_mth <= '2'
and hrch_clm_year >= '2017' AND hrch_clm_year <= '2017'
ORDER BY hrch_clm_no;
It works fine. However, it doesn't work if I want to get a result for a different year, for example, from year 2016 to 2017. So I made the adjustment to that query:
SELECT *
FROM c60_hrd.hrclhf
WHERE (hrch_clm_mth >= '12' AND hrch_clm_year >= '2016')
OR (hrch_clm_mth <= '2' and hrch_clm_year <= '2017')
ORDER BY hrch_clm_no;
It works fine to get the result for the different year. But when I change to that query, I get wrong results if I want to query within the same year. For example, from month 2 to 3 and year 2017. It displays a record from month 1 to 3 which I don't want. It supposedly displays a record from month 2 and 3 only.
Kindly help me.
Try to use this WHERE clause:
WHERE STR_TO_DATE(CONCAT_WS('-', hrch_clm_year, hrch_clm_mth,'1'),'%Y-%m-%d') BETWEEN '2017-02-01' AND '2017-03-01'
If you want to use year and month components separately, then you can do following:
SELECT *
FROM c60_hrd.hrclhf
WHERE (hrch_clm_mth + 12*hrch_clm_year) BETWEEN (#StartMonth + 12*#StartYear) AND (#FinishMonth + 12*#FinishYear)
ORDER BY hrch_clm_no;

Query returns null instead of 0 [duplicate]

This question already has answers here:
How to generate data in MySQL?
(4 answers)
Closed 8 years ago.
I have a query that counts all Work ID Numbers by month and year and then creates a chart for the past 13 months using jpgraph. It works great except there are no Work ID Numbers in July so the chart totally skips July.
Query Results:
5
16
15
11
3
12
4
8
2
9
13
12
Desired Results:
5
16
15
11
3
12
0
4
8
2
9
13
12
As you can see I need the (0) zero in order for my chart to work, however since there are no Work ID Number in July my query simply skips it. Here is my query:
SELECT COUNT( WORK_ID_NUM ) AS count,
DATE FROM SERVICE_JOBS
WHERE (DATE BETWEEN '$lastyear' AND '$date')
AND JOB_TYPE LIKE 'Street Light'
GROUP BY YEAR( DATE ), MONTH( DATE )
ORDER BY DATE
sqlFiddle Demo
SELECT IFNULL(count,0) as count,theDate as Date
FROM
(SELECT #month := #month+INTERVAL 1 MONTH as theDate
FROM service_jobs,(SELECT #month:='$lastyear' - INTERVAL 1 MONTH)as T1
LIMIT 13)as T2
LEFT JOIN
(SELECT COUNT(WORK_ID_NUM)as count,DATE
FROM service_jobs
WHERE (DATE BETWEEN '$lastyear' AND '$date')
AND JOB_TYPE LIKE 'Street Light'
GROUP BY YEAR(DATE), MONTH(DATE)) T3
ON (YEAR(theDate) = YEAR(DATE) AND MONTH(theDate) = MONTH(DATE))
ORDER BY theDate;
To get your query to return a row for July, you need to have a row with July in it. You could create a table with all the dates between $lastyear and $date in it and then outer join from that to SERVICE_JOB.
SELECT COUNT( WORK_ID_NUM ) AS count,
allDates.DATE
FROM AllDates
Left outer join SERVICE_JOB
on AllDates.DATE = SERVICE_JOB.DATE
WHERE (AllDates.DATE BETWEEN '$lastyear' AND '$date') AND
(SERVICE_JOB.WORK_ID_NUM is NULL OR JOB_TYPE LIKE 'Street Light')
GROUP BY YEAR( AllDates.DATE ), MONTH( AllDates.DATE )
ORDER BY AllDates.DATE
In SQL Server it would be pretty easy to make a Common Table Expression that could fill AllDates for you based on $lastyear and $date. Not sure about MySql.

MySQL: group by date RANGE?

OK I have this query that groups 2 columns together quite nicely:
SELECT search_query_keyword, search_query_date, COUNT(1) as count
FROM search_queries
WHERE search_query_date >= '.$from.' AND search_query_date <= '.$to.'
GROUP BY search_query_keyword, search_query_date
ORDER BY count DESC
LIMIT 10
But what if I want to group by a date RANGE instead of just a date? Is there a way to do that?
Thanks!
EDIT: OK these answers are pretty complicated and I think what I want can be acheived a lot easier so let me re-explain. I want to select keywords over a time period ">= 20090601 AND <= 20090604" for example. But instead of getting repeated keywords I would rather just get the keyword ounce and how many times it occured. So for example instead of this:
keyword: foo
keyword: foo
keyword: foo
keyword: bar
keyword: bar
I would get:
keyword: foo, count: 3
keyword: bar, count: 2
I'm not exactly sure about the date range grouping -- you'd have to define the date ranging that you would want and then maybe you could UNION those queries:
SELECT
'Range 1' AS 'date_range',
search_query_keyword
FROM search_queries
WHERE search_query_date >= '.$fromRange1.' AND search_query_date <= '.$toRange1.'
UNION
SELECT
'Range 2' AS 'date_range',
search_query_keyword
FROM search_queries
WHERE search_query_date >= '.$fromRange2.' AND search_query_date <= '.$toRange2.'
GROUP BY 1,2
Or if you wanted to put them within a grouping of how many days old like "30 days, 60 days, etc" you could do this:
SELECT
(DATEDIFF(search_query_date, NOW()) / 30) AS date_group,
search_query_keyword
FROM search_queries
GROUP BY date_group, search_query_keyword
EDIT: Based on the further information you provided, this query should produce what you want:
SELECT
search_query_keyword,
COUNT(search_query_keyword) AS keyword_count
FROM search_queries
WHERE search_query_date >= '.$from.' AND search_query_date <= '.$to.'
GROUP BY search_query_keyword
You could group on a CASE statement or on the result of a function. For instance:
SELECT search_query_keyword, QUARTER(search_query_date), COUNT(1) as count
FROM search_queries
WHERE search_query_date >= '.$from.' AND search_query_date <= '.$to.'
GROUP BY search_query_keyword, QUARTER(search_query_date)
ORDER BY count DESC
look into the different DATE-based functions and build based on that, such as
select YEAR( of your date ) + MONTH( of your date ) as ByYrMonth
but the result in above case would need to be converted to character to prevent a year of 2009 + January ( month 1) = 2010 also getting falsely grouped with 2008 + February (month 2 ) = 2010, etc... Your string should end up as something like:
...
200811
200812
200901
200902
200903
...
If you wanted by calendar Quarters, you would have to do a INTEGER of the (month -1) divided by 4 so...
Jan (-1) = 0 / 4 = 0
Feb (-1) = 1 / 4 = 0
Mar (-1) = 2 / 4 = 0
Apr (-1) = 3 / 4 = 0
May (-1) = 4 / 4 = 1
June (-1)= 5 / 4 = 1 ... etc...
Yes, a previous example explicitly reference the QUARTER() function that handles more nicely, but if also doing based on aging, such as 30, 60, 90 days, you could apply the similar math above but divide by 30 for your groups.