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`;
:)
Related
Below is the Invoices table:
I am trying to make a sql query which gives me output based on due_date range with the sum of balance_amount group by company_id
My try:
select invoices.company_id,
SUM(invoices_cmonth.balance_amount) as cmonth,
SUM(invoices_1month.balance_amount) as 1month,
SUM(invoices_2month.balance_amount) as 2month
from `invoices`
LEFT JOIN invoices invoices_cmonth
ON (invoices.company_id = invoices_cmonth.company_id and invoices_cmonth.due_date >= '2021-11-10')
LEFT JOIN invoices invoices_1month
ON (invoices.company_id = invoices_1month.company_id and invoices_1month.due_date < '2021-11-10' and invoices_1month.due_date >= '2021-10-10')
LEFT JOIN invoices invoices_2month
ON (invoices.company_id = invoices_2month.company_id and invoices_2month.due_date < '2021-10-10' and invoices_2month.due_date >= '2021-9-10')
where invoices.`status` = 'ACTIVE'
and invoices.`balance_amount` > 0
and `invoices`.`deleted_at` is null
group by invoices.`company_id`
But it is giving me wrong figures in balance amount.
I suggest just making a single pass over the invoices table using conditional aggregation for the various time windows:
SELECT
company_id,
SUM(CASE WHEN due_date >= '2021-11-10' THEN balance_amount ELSE 0 END) AS cmonth,
SUM(CASE WHEN due_date >= '2021-10-10' AND due_date < '2021-11-10'
THEN balance_amount ELSE 0 END) AS 1month,
SUM(CASE WHEN due_date >= '2021-09-10' AND due_date < '2021-10-10'
THEN balance_amount ELSE 0 END) AS 2month
FROM invoices
WHERE
status = 'ACTIVE' AND balance_amount > 0 AND deleted_at IS NULL
GROUP BY
company_id;
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.
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 need to understand how mysql interprets or executes such a subquery:
SELECT SUM(tp),SUM(ep),SUM(mp) FROM
(
SELECT Avg(case date_format(PS_DATE,'%Y') when '2005' then nvl(tp,0) else 0 end) tp,
Avg(case date_format(PS_DATE,'%Y') when '2005' then nvl(ep,0) else 0 end) ep,
Avg(case date_format(PS_DATE,'%Y') when '2005' then nvl(mp,0) else 0 end) mp
FROM M_DAILY
WHERE PS_DATE >= date ('2005-01-01') and PS_DATE <= date ('2005-12-31');
) As T
Can someone interpret how such a query is interpreted (in words)please!
For the year 2005, it finds the SUM of average values of the columns tp, ep and mp. While doing this null values are considered as 0. As the dates are filtered for year 2005, the above code can be simplified as
SELECT SUM(tp),SUM(ep),SUM(mp) FROM
(
SELECT Avg(nvl(tp,0)) tp,
Avg(nvl(ep,0)) ep,
Avg(nvl(mp,0)) mp
FROM M_DAILY
WHERE PS_DATE >= date ('2005-01-01') and PS_DATE <= date ('2005-12-31');
) As T
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