I am working with a query where I want to display number of upcoming dates. The following query returns 0 even though there are dates greater than current date. Please help me to solve this problem.
SELECT (case when b.booked_date > cast(now() as date) then sum(1) else sum(0) end) as upcoming_booked_facilities
from svk_apt_book_facilities b
where b.customer_id = 1
and b.association_id = 1
and b.is_active = 1
group by b.facility_id
You need to sum a CASE expression to do conditional aggregation:
SELECT
facility_id,
SUM(CASE WHEN booked_date > CURDATE() THEN 1 ELSE 0 END) AS upcoming_booked_facilities
FROM svk_apt_book_facilities
WHERE
customer_id = 1 AND
association_id = 1 AND
is_active = 1
GROUP BY
facility_id;
You were trying to use the sum as the predicate of the CASE expression, which is probably not what you want. Note that I am also selecting the facility_id, since you are grouping by that column. If you instead want a conditional sum over the entire table, then don't select or group by facility.
Related
I have table as below :-
With help of MySql query, I want result as below:
date total read unread
2018-01-31 8 4 4
2018-02-01 2 2 0
Try this:
SELECT date, COUNT(*) as total,
SUM(CASE WHEN read = 1 THEN 1 ELSE 0) as read
SUM(CASE WHEN read = 0 THEN 1 ELSE 0) as unread
FROM yourtable
GROUP BY date
you can use case for aggregate the filtered value for read
select date
, count(*), sum(case when read=1 then 1 else 0 end ) as read
, sum(case when read=0 then 1 else 0 end ) as unread
from my_table
group by date
Try This we don't need case in the read column as 1 means read so we simply sum the value. It will help in the performance if we are dealing with the huge data:
SELECT date,
COUNT(*) as total,
SUM(read) as read --Case not needed here
SUM(CASE WHEN read = 0 THEN 1 ELSE 0) as unread
FROM yourtable
GROUP BY date
You have to group rows by date using group by, then you can use count to count the total number of rows within each date group (= total column).
In order to obtain the number of read and unread, you can sum read and unread value
SELECT date
, COUNT(*) AS total
, SUM(READ) AS READ
, SUM(CASE WHEN READ = 0 THEN 1 ELSE 0 END) AS unread
FROM mytable
GROUP BY date
The first case statement i got the correct result but in the second one
Why i got an NULL result Where my second case statement the counter = 2
this is the result i have an image
Query Result that i got Null data in second statement when i grouped by on my date
SELECT DISTINCT date,log,
CASE
WHEN note = 'HOLIDAY' AND counter = 1
THEN 'HOLIDAY'
END note1,
CASE
WHEN note = 'HOLIDAY' AND counter = 2
THEN 'HOLIDAY'
END note2,
FROM timesheet
WHERE timesheet.empid='40' AND date <= CURDATE() AND YEAR(date)= YEAR(CURDATE())
AND MONTH(date) = MONTH(CURDATE())
GROUP BY date
ORDER BY date DESC;
You're using GROUP BY wrong. The rule is that each column in your SELECT clause is either also in your GROUP BY clause or an aggregate function (like count, min, max, avg) must be applied to it.
When you don't follow this rule, a random row for each group is displayed. In your case, when you really have data with note = 'HOLIDAY' AND counter = 2, the rows for the group might look like this
NULL
HOLIDAY
NULL
NULL
but after collapsing (when it's outputted by the select), just the first row is displayed, therefore the NULL value.
Try it like this:
SELECT date,
MIN(log), /*or maybe you want to group by this column, too? */
MAX(CASE
WHEN note = 'HOLIDAY' AND counter = 1
THEN 'HOLIDAY'
END) note1,
MAX(CASE
WHEN note = 'HOLIDAY' AND counter = 2
THEN 'HOLIDAY'
END) note2,
FROM timesheet
WHERE timesheet.empid='40' AND date <= CURDATE() AND YEAR(date)= YEAR(CURDATE())
AND MONTH(date) = MONTH(CURDATE())
GROUP BY date
ORDER BY date DESC;
Also note, that I removed the DISTINCT. Your GROUP BY already does that.
I'm new to SQL and trying to create a total summary of a working SQL query. It's listing the total results from one month of data.
Now I need the total values of the outcome of the query.
So I created a 'query in a query' piece of SQL, but it ain't working because my lack of SQL knowledge. I guess it's an easy fix for you pro's :-)
The working SQL query with the daily outcome of one month:
SELECT
DATE_FORMAT(date, '%d/%m/%y') AS Datum,
COUNT(*) AS Berichten,
SUM(CASE WHEN virusinfected>0 THEN 1 ELSE 0 END) AS Virus,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND isspam>0 THEN 1 ELSE 0 END) AS Ongewenst,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND (isspam=1) AND isrblspam>0 THEN 1 ELSE 0 END) AS RBL,
SUM(size) AS Grootte
FROM
maillog
WHERE
1=1
AND (1=1)
AND
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain1.nl'
OR
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain2.nl'
GROUP BY
Datum
ORDER BY
date
The incorrect query trying to create the monthly totals:
SELECT Datum,
SUM(Berichten) AS Berichten,
SUM(Virus) AS Virus,
SUM(Ongewenst) AS Ongewenst,
SUM(RBL) AS RBL,
SUM(Grootte) AS Grootte,
FROM ( SELECT
DATE_FORMAT(date, '%d/%m/%y') AS Datum,
COUNT(*) AS Berichten,
SUM(CASE WHEN virusinfected>0 THEN 1 ELSE 0 END) AS Virus,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND isspam>0 THEN 1 ELSE 0 END) AS Ongewenst,
SUM(CASE WHEN (virusinfected=0 OR virusinfected IS NULL) AND (isspam=1) AND isrblspam>0 THEN 1 ELSE 0 END) AS RBL,
SUM(size) AS Grootte
FROM
maillog
WHERE
1=1
AND (1=1)
AND
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain1.nl'
OR
date < '2017-04-01'
AND
date >= '2017-03-01'
AND
to_domain = 'domain2.nl'
GROUP BY
Datum
ORDER BY
date
) t
GROUP BY Datum;
Thanks in advance.
What you want can be done with just a little addition to your first SQL statement: add with rollup after the group by clause:
GROUP BY Datum WITH ROLLUP
It will run more efficiently than the version with sub-query, although it could work that way, but you should then remove the outer group by clause and not select Datum there, since you don't want the totals per date any more, but overall.
Still, you will lose the details and only get the overall totals then. You would have to use a union with your original query to get both levels of totals. You can imagine that the with rollup modifier will do the job more efficiently.
I Have wrote sql query something like this :
SELECT `petugas_input`,
COUNT(`petugas_input`) AS `01-MAR`,
COUNT(`petugas_input`) AS `02-MAR`,
COUNT(`petugas_input`) AS `03-MAR`
FROM `tabel_arsip`
WHERE `tgl_input_arsip`>='2016-03-01 00:00:00' AND `tgl_input_arsip`<='2016-03-01 23:59:59'
GROUP BY `petugas_input`
and its generate result like this
My question is how to add criteria to the aliases column so that it will show different value on different date. (not the same value in the date column as above)
You'd have to rely on a little complex grouping:
SELECT
`petugas_input`,
SUM(CASE WHEN DATE(tgl_input_arsip) = '2016-03-01' THEN 1 ELSE 0 END) AS `01-MAR`,
SUM(CASE WHEN DATE(tgl_input_arsip) = '2016-03-02' THEN 1 ELSE 0 END) AS `02-MAR`,
SUM(CASE WHEN DATE(tgl_input_arsip) = '2016-03-03' THEN 1 ELSE 0 END) AS `03-MAR`,
FROM `tabel_arsip`
WHERE `tgl_input_arsip`>='2016-03-01 00:00:00' AND `tgl_input_arsip`<='2016-03-01 23:59:59'
GROUP BY `petugas_input`
You should not think for these hard-coded column aliases rather make a query for each petugas_input and for each date (within the given date range) along with the count.
Something like this:
SELECT
`petugas_input`,
DATE(`tgl_input_arsip`) `date`,
COUNT(*) total
FROM `tabel_arsip`
WHERE `tgl_input_arsip`>='2016-03-01 00:00:00' AND `tgl_input_arsip`<='2016-03-01 23:59:59'
GROUP BY `petugas_input`,`date`;
And you will get the following output structure:
petugas_input date total
A yyyy-mm-dd n1
B yyyy-mm-dd n2
Try this one:
SELECT `petugas_input`,
COUNT(CASE WHEN DATE(tgl_input_arsip) = '2016-03-01' THEN petugas_input ELSE 0 END) AS `01-MAR`,
COUNT(CASE WHEN DATE(tgl_input_arsip) = '2016-03-02' THEN petugas_input ELSE 0 END) AS `02-MAR`,
COUNT(CASE WHEN DATE(tgl_input_arsip) = '2016-03-03' THEN petugas_input ELSE 0 END) AS `03-MAR`
FROM `tabel_arsip`
WHERE `tgl_input_arsip`>='2016-03-01 00:00:00' AND `tgl_input_arsip`<='2016-03-03 23:59:59'
GROUP BY `petugas_input`;
:)
How can you Select two columns and have each column test for it's own condition and not the other's ?
Let's say I have a select that Count every records in a table. In one column I want every records from this week, and in the second one I want all record since the beginning of the year.
I have two conditions but they each apply to a specific column :
WHERE date BETWEEN #Monday AND #SUNDAY /* Weekly */
WHERE date >= #JanuaryFirst /* Annual */
But can't just put it like this because I will only get this week's record in both columns. I thought I could use an IFcondition but I don't think I can simply say "If you are column A test for this, if not test for the second one".
Here is a version that doesn't yield multiple scans:
select vehicule,
weekly = SUM(CASE WHEN date BETWEEN #Monday AND #SUNDAY THEN 1 ELSE 0 END),
annual = SUM(CASE WHEN date >= #JanuaryFirst THEN 1 ELSE 0 END)
from dbo.tablename AS t
GROUP BY vehicule;
Or you could also try the slightly less verbose:
select vehicule,
weekly = COUNT(CASE WHEN date BETWEEN #Monday AND #SUNDAY THEN 1 END),
annual = COUNT(CASE WHEN date >= #JanuaryFirst THEN 1 END)
from dbo.tablename AS t
GROUP BY vehicule;
Use INNER SELECTS, like this:
select vehicule,
(select count(*) from tablename t1 where t1.vehicule = t.vehicule and date BETWEEN #Monday AND #SUNDAY) as 'Weekly',
(select count(*) from tablename t1 where t1.vehicule = t.vehicule and date >= #JanuaryFirst) as 'Annual'
from tablename t
If you want to avoid subqueries you can use:
select vehicule,
sum(case when date BETWEEN #Monday AND #SUNDAY then 1 else 0 end) as 'Weekly',
sum(case when date >= #JanuaryFirst then 1 else 0 end) as 'Annual'
group by vehicule