(Using SQL Server 2008) I could easily get this to work if I built a view, and then a query on the view, but I want to perform this in one SQL query. I have a table that contains two columns (DeliveredDate (DateTime), Delivered (Varchar)). I am first converting DeliveredDate to Date only, and then grouping by Date. At the same time I am performing a Count on Delivered (column is either YES or NULL). Here is what I use to accomplish this portion:
SELECT CAST([DeliveredDate] As Date),
COUNT([Delivered])
FROM [TableName]
GROUP BY CAST([DeliveredDate] As Date)
ORDER BY CAST([DeliveredDate] As Date)
As an output, I get something like:
DeliveredDate | Delivered
2012-04-24 10
2012-04-25 500
2012-04-26 422
2012-04-27 33
What I'm looking for is something like this:
DeliveredDate | Delivered | RunningTotal
2012-04-24 10 10
2012-04-25 500 510
2012-04-26 422 932
2012-04-27 33 965
I've tried various examples I've seen out there, but none seem to match this scenario of performing a Count and a RunningTotal on said Count.
If you are using a product that implements ordered OVER clauses for SUM, you can do something like this:
select
cast(DeliveredDate as date) as DeliveredDate,
count(Delivered) as Delivered,
sum(count(Delivered)) over (
order by DeliveredDate
) as RunningTotal
from Orders
group by OrderDate
order by OrderDate;
Your expression count(Delivered) is a bit strange. Just to be sure it's what you want: it will count the number of rows on the particular date for which the value in the Delivered column is NOT NULL.
I'm not sure if a CTE counts as a view but this will work in SQL 2005+ which Does Not Support ordered OVER clauses for SUM,
WITH cte (DeliveredDate, Delivered)
AS (SELECT Cast([DeliveredDate] AS DATE) DeliveredDate,
Count([Delivered]) Delivered
FROM [TableName]
GROUP BY Cast([DeliveredDate] AS DATE))
SELECT d1.delivereddate,
d1.delivered,
Sum(d2.Delivered) RunningTotal
FROM cte d1
LEFT JOIN cte d2
ON d1.delivereddate >= d2.DeliveredDate
GROUP BY d1.delivereddate,
d1.delivered
ORDER BY d1.delivereddate
Related
Hello there I have the following doubt I want to count how many times in a month I enter data.
My database is:
Date:
10/2010
10/2010
09/2010
08/2010
I have the following query.
SELECT DISTINCT (date)
FROM employee
WHERE date
IN (SELECT date
FROM employee
GROUP BY date
HAVING count( date ) >0)
ORDER BY date DESC;
This query gives me:
Date:
10/2017
8/2017
9/2017
But I want you to give me something like that.
Count | Date
2 | 10/2017
1 | 9/2017
1 | 10/2017
I hope I have explained my regards.
You're overcomplicating it; no subquery, or DISTINCT, needed.
SELECT `date`, count(*)
FROM `employee`
GROUP BY `date`
HAVING count(*) > 0
ORDER BY `date` DESC;
I am a little confused as to what reason you would have for the HAVING count() > 0 though; the only way something could have a zero count would mean it wasn't in the table (and therefore wouldn't show up anyway).
Other observations:
DISTINCT is not a function; enclosing the date in parenthesis in the SELECT clause has absolutely no effect. (Also, DISTINCT is almost never appropriate for a GROUPing query.)
COUNT(somefield) is the same as COUNT(1), COUNT(*). If you want the count of unique values you can do COUNT(DISTINCT somefield); but it wouldn't make sense to COUNT(DISTINCT groupingfield) as that would always result in 1.
The query you wrote is a bit complicated. Distinct and group by are doing the same thing for you here. When you do a group by count will automatically give you the count of grouped rows. Also you will have unique dates as well. Try this.
SELECT count(date), date
FROM employee
GROUP BY date
HAVING count( date ) >0
ORDER BY date DESC;
I have run into an issue with MySQL's ROLLUP and dealing with the resulting NULLs. The IFNULL/COALESCE functions work well with plain columns, but seem to break down when used with date functions. Examples follow:
SELECT
YEAR(date_time) AS Year,
count(x) AS Count
FROM mytable
GROUP BY year WITH ROLLUP
returns (as expected)
Year Count
---- -----
2015 3
2016 2
NULL 5
When I query for non-date columns (varchar, for example), I can deal with the NULL values by using IFNULL or COALESCE functions to replace NULL values with strings. However, when I apply the same logic to the above query, it does not seem to work.
SELECT
COALESCE(YEAR(date_time), 'moo') AS Year,
count(x) AS Count
FROM mytable
GROUP BY year WITH ROLLUP
or
SELECT
IFNULL(YEAR(date_time), 'moo') AS 'year',
count(x) AS Count
FROM mytable
GROUP BY year WITH ROLLUP
returns
Year Count
---- -----
2015 3
2016 2
NULL 5
instead of expected
Year Count
---- -----
2015 3
2016 2
moo 5
Any ideas, suggestions?
If you're trying to target the NULL's generated during the aggregate rollup calculations (as opposed to NULLs in your raw data), you're referring to the wrong NULLs. If so, this is probably what you are trying to do:
SELECT
IFNULL(m.year, 'moo')
FROM
(SELECT
YEAR(date_time) AS 'year'
FROM
mytable
GROUP BY
year
WITH ROLLUP) m
Here's the sqlfiddle.
I have this table:
-----------------------------------------------------------
| id | name | date | count | balance |
-----------------------------------------------------------
1 a 0000-00-00 1 10
2 b 2014-10-02 1 20
3 c 2014-09-01 1 30
4 d 2014-09-16 1 40
I need to get the SUM of the four count & balance column on my SELECT, then order it by the date in ascending but I need to make sure it should not be the 0000-00-00. I tried this syntax but it does not order the date the way I wanted.
SELECT
date,
SUM(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
ORDER BY date ASC
My expected output:
-------------------------------------------
| date | count | balance |
-------------------------------------------
2014-09-01 4 90
Use MIN and NULLIF functions:
SELECT
MIN(NULLIF(date, '0000-00-00')) AS min_date,
SUM(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
Test it here: http://sqlfiddle.com/#!2/d43acf/1
I wish I understood the point in having a 0000-00-00 date as opposed to having null so only one possibility needs ruling out... Anyway at first I would assume you might want to get the total balances of each day and would require a query along these lines
SELECT
date,
sum(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
WHERE date <> '0000-00-00'
GROUP BY date
ORDER BY date
which would output
2014-09-01 1 30
2014-09-16 1 40
2014-10-02 1 20
but as it stands it appears you don't, I'm not one hundred percent sure what your ultimate goal is in terms of future querying so I will guess you want a historical value of balances up to the current date, ruling out the weird zero date thing. In which case you might want a greater than WHERE clause, and presumably just the lowest value in the date column to show the total from this date like so:
SELECT
min(date) AS date,
sum(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
WHERE date > '0000-00-00'
since it would ignore the invalid date it will return
2014-09-01 3 80
I hope this is of some use.
Edit:
if you absolutely require all values then you will want to use a subquery to retrieve and rule out the exceptional date result like so:
SELECT
(SELECT min(date) FROM tbl WHERE date > '0000-00-00') AS date,
sum(count) AS deposit_counts,
SUM(balance) AS balance_sum
FROM tbl
or as above, nullif on your date query should work too
I have a MySQL table where there are many rows for each person, and I want to write a query which aggregates rows with special constraint. (one per person)
For example, lets say the table is consist of following data.
name date reason
---------------------------------------
John 2013-04-01 14:00:00 Vacation
John 2013-03-31 18:00:00 Sick
Ted 2012-05-06 20:00:00 Sick
Ted 2012-02-20 01:00:00 Vacation
John 2011-12-21 00:00:00 Sick
Bob 2011-04-02 20:00:00 Sick
I want to see the distribution of 'reason' column. If I just write a query like below
select reason, count(*) as count from table group by reason
then I will be able to see number of reasons for this table overall.
reason count
------------------
Sick 4
Vacation 2
However, I am only interested in single reason from each person. The reason that should be counted should be from a row with latest date from the person's records. For example, John's latest reason would be Vacation while Ted's latest reason would be Sick. And Bob's latest reason (and the only reason) is Sick.
The expected result for that query should be like below. (Sum of count will be 3 because there are only 3 people)
reason count
-----------------
Sick 2
Vacation 1
Is it possible to write a query such that single latest reason will be counted when I want to see distribution(count) of reasons?
Here are some facts about the table.
The table has tens of millions of rows
For most of times, each person has one reason.
Some people have multiple reasons, but 99.99% of people have fewer than 5 reasons.
There are about 30 different reasons while there are millions of distinct names.
The table is partitioned based on date range.
SELECT T.REASON, COUNT(*)
FROM
(
SELECT PERSON, MAX(DATE) AS MAX_DATE
FROM TABLE-NAME
GROUP BY PERSON
) A, TABLE-NAME T
WHERE T.PERSON = A.PERSON AND T.DATE = A.MAX_DATE
GROUP BY T.REASON
Try this
select reason, count(*) from
(select reason from table where date in
(select max(date) from table group by name)) t
group by reason
In MySQL, it's not very efficient to do this kind of query since you don't have access to tools like partitionning query in SQL Server or Oracle.
You can still emulate it by doing a subquery and retrieve the rows based on the condition you need, here the maximum date :
SELECT t.reason, COUNT(1)
FROM
(
SELECT name, MAX(adate) AS maxDate
FROM #aTable
GROUP BY name
) maxDateRows
INNER JOIN #aTable t ON maxDateRows.name = t.name
AND maxDateRows.maxDate = t.adate
GROUP BY t.reason
You can see a sample here.
Test this query on your samples, but I'm afraid that it will be slow as hell.
For your information, you can do the same thing in a more elegant and much much faster way in SQL Server :
SELECT reason, COUNT(1)
FROM
(
SELECT name
, reason
, RANK() OVER(PARTITION BY name ORDER BY adate DESC) as Rank
FROM #aTable
) AS rankTable
WHERE Rank = 1
GROUP BY reason
The sample is here
If you are really stuck to MySql, and the first query is too slow, then you can split the problem.
Do a first query creating a table:
CREATE TABLE maxDateRows AS
SELECT name, MAX(adate) AS maxDate
FROM #aTable
GROUP BY name
Then create index on both name and maxDate.
Finally, get the results :
SELECT t.reason, COUNT(1)
FROM maxDateRows m
INNER JOIN #aTable t ON m.name = t.name
AND m.maxDate = t.adate
GROUP BY t.reason
The solution you are looking for seems to be solved by this query :
select
reason,
count(*)
from (select * from tablename group by name) abc
group by
reason
It is quite fast and simple. You can view the SQL Fiddle
Apologies if this answer duplicates an existing. Maybe I'm suffering from some form aphasia but I cannot see it...
SELECT x.reason
, COUNT(*)
FROM absentism x
JOIN
( SELECT name,MAX(date) max_date FROM absentism GROUP BY name) y
ON y.name = x.name
AND y.max_date = x.date
GROUP
BY reason;
I am trying to write a query which will give me the last entry of each month in a table called transactions. I believe I am halfway there as I have the following query which groups all the entries by month then selects the highest id in each group which is the last entry for each month.
SELECT max(id),
EXTRACT(YEAR_MONTH FROM date) as yyyymm
FROM transactions
GROUP BY yyyymm
Gives the correct results
id yyyymm
100 201006
105 201007
111 201008
118 201009
120 201010
I don’t know how to then run a query on the same table but select the balance column where it matches the id from the first query to give results
id balance date
120 10000 2010-10-08
118 11000 2010-09-29
I've tried subqueries and looked at joins but i'm not sure how to go about using them.
You can make your first select an inline view, and then join to it. Something like this (not tested, but should give you the idea):
SELECT x.id
, t.balance
, t.date
FROM your_table t
/* here, we make your select an inline view, then we can join to it */
, (SELECT max(id) id,
EXTRACT(YEAR_MONTH FROM date) as yyyymm
FROM transactions
GROUP BY yyyymm) x
WHERE t.id = x.id