Group by year month sql, when no entry write 0 - sql

I have an sql query, but I want to show months, where no entries. Now just show entries when it has entry. Here is the code:
SELECT YEAR(T0.[Recontact]) AS 'Év', MONTH(T0.[Recontact]) AS 'Hónap',
T1.[SlpName], COUNT(T0.[ClgCode]) AS 'Tárgyalások'
FROM OCLG T0
INNER JOIN OSLP T1 ON T0.[SlpCode] = T1.[SlpCode]
WHERE T0.[Action] = 'M' AND
T0.[Recontact] >= 'date' AND
T0.[Recontact] <= 'date2' AND
T1.[SlpName] = 'user name'
GROUP BY YEAR(T0.[Recontact]), MONTH(T0.[Recontact]), T1.[SlpName]
ORDER BY 1,2

If the year + month is totally missing from your data, you'll need to construct an empty row somewhere that can be shown in the place. You can create either a calendar table (one row per day) or a month table (one row per month). That can also be a "virtual" tally table constructed in a CTE or similar.
Once you have that, you can do something like this:
select
M.Year, M.Month, X.SlpName, isnull(X.CODES,0) as CODES
from
months M
outer apply (
SELECT
YEAR(T0.[Recontact]) as Year,
MONTH(T0.[Recontact]) AS Month,
T1.[SlpName],
COUNT(T0.[ClgCode]) AS CODES
FROM OCLG T0
INNER JOIN OSLP T1 ON T0.[SlpCode] = T1.[SlpCode]
WHERE T0.[Action] = 'M' AND
T0.[Recontact] >= 'date' AND
T0.[Recontact] <= 'date2' AND
T1.[SlpName] = 'user name'
GROUP BY YEAR(T0.[Recontact]), MONTH(T0.[Recontact]), T1.[SlpName]
) X on X.Year = M.Year and X.Month = M.Month
where M.MONTHDATE >= 'date' and M.MONTHDATE <= 'date2'
ORDER BY 1,2
This was with an imaginary month table that has year, month and monthdate columns, and the date is the first of the month -- you'll still have to check that the range you're fetching is correct.
I haven't tested this, but it should work.

Replace INNER JOIN with LEFT JOIN in your request to get NULL results.
SELECT YEAR(T0.[Recontact]) AS 'Év', MONTH(T0.[Recontact]) AS 'Hónap',
T1.[SlpName], COUNT(T0.[ClgCode]) AS 'Tárgyalások'
FROM OCLG T0
LEFT JOIN OSLP T1 ON (T0.[SlpCode] = T1.[SlpCode]
AND T1.[SlpName] = 'user name')
WHERE T0.[Action] = 'M'
AND T0.[Recontact] >= 'date'
AND T0.[Recontact] <= 'date2'
GROUP BY YEAR(T0.[Recontact]), MONTH(T0.[Recontact]), T1.[SlpName]
ORDER BY 1,2

Replace INNER JOIN with LEFT JOIN in your request to get NULL results.
to learn more visit :
http://academy.comingweek.com/sql-groupby-clause/

Related

Print result from 2 queries in different columns of one table

I am trying to output result from 2 queries in one table but no luck. Tried with UNION and with this template
SELECT x.a, y.b FROM (SELECT * from a) as x, (SELECT * FROM b) as y
with no luck. My queries are:
Select
Sum('.MAIN_DB_PREFIX.'facturedet.qty) As qty_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid,
'.MAIN_DB_PREFIX.'facture.datef,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facturedet
Inner Join
'.MAIN_DB_PREFIX.'facture On '.MAIN_DB_PREFIX.'facturedet.fk_facture = '.MAIN_DB_PREFIX.'facture.rowid Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
ORDER BY
qty_sum DESC
and
Select
Sum('.MAIN_DB_PREFIX.'facture.total) As total_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid,
'.MAIN_DB_PREFIX.'facture.datef,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facture Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
ORDER BY
total_sum DESC
With both UNION or combined query as mentioned above, I get blank result and no errors.
Also, I cannot wrap the select in brackets and use an alias like (query) a UNION (query2) b as this also brings blank output.
I can output first name + last name in column one of a table, sum_qty on second, some calculation is made based on the qty and it goes in the third column. In the fourth column, I need to output total_sum
Digged here like 20 threads and tried different solutions but no result.
Full code: https://pastebin.com/bie0LXH9
This should achieve the desired result (ie. the resultset that you need to output your table) using the UNION that you were attempting (although a more efficient query could possibly be achieved using a Common Table Expression - which may or may not be available to you, depending on your RDBMS, and the version thereof).
SELECT
firstname,
lastname,
rowid,
SUM(IFNULL(qty_sum, 0)) AS qty_sum,
SUM(IFNULL(total_sum, 0)) AS total_sum
FROM
(
Select
Sum('.MAIN_DB_PREFIX.'facturedet.qty) As qty_sum,
0 AS total_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facturedet
Inner Join
'.MAIN_DB_PREFIX.'facture On '.MAIN_DB_PREFIX.'facturedet.fk_facture = '.MAIN_DB_PREFIX.'facture.rowid Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
UNION ALL
Select
0 AS qty_sum,
Sum('.MAIN_DB_PREFIX.'facture.total) As total_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facture Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
) AS tbl_all
GROUP BY rowid
ORDER BY
total_sum DESC

Sum amount of table where a particular column has same value

I am trying to find the sum of amount in the table according to the value of month. This is my query
SELECT to_char(
to_timestamp(
date_part('month', p.date_from)::text,
'MM'
),
'Month'
) as Month,
p.employee_id, p.id as payslip_id,
p.date_from, p.date_to, pl.amount
FROM hr_payslip p
INNER JOIN hr_payslip_line pl
ON (p.id = pl.slip_id AND pl.code = 'NET');
Output:
Need:
I need to group by the month and sum value of column amount.
Perhaps a simple GROUP BY is all you are asking for:
SELECT to_char(p.date_from, 'Month') as month,
sum(pl.amount)
FROM hr_payslip p
INNER JOIN hr_payslip_line pl
ON (p.id = pl.slip_id AND pl.code = 'NET')
GROUP BY to_char(p.date_from, 'Month');
I did it using the following query
select to_char(to_timestamp (date_part('month', p.date_from)::text, 'MM'), 'Month') as Month,
sum(pl.amount) from hr_payslip p
INNER JOIN hr_payslip_line pl on (p.id = pl.slip_id and pl.code = 'NET') group by month
output:

Ms SQL date range query: month to month OK but whole year incorrect results

I have a query below that returns the correct results when executed month by month. i.e. 1jan -31st jan, 2nd feb - 28th feb, 1st march -31st march.. etc etc.
but when i set historydate>= '2017-01-01' to capture the whole year, it returns completely wrong results. Any ideas? I'm on mssql
SELECT DISTINCT
cl.id AS id, cl.[KEY] AS issuekey,
MAX(historyDate) AS releaseDate,
m.issueType,
m.priority
FROM d_jira_changelog cl
JOIN d_jira_changelog_items ci ON ci.historyId = cl.historyId
JOIN d_jira_main m ON m.id = cl.id
WHERE(ci.changeitemfrom = 'Phase1'
AND ci.changeItemTo = 'Phase2')
AND changeItemField = 'status'
AND m.projectkey IN('ABC', 'CBA', 'XYZ', 'YOYO')
AND historydate >= '2017-01-01'
GROUP BY cl."id", cl."key", m.issueType, m.priority;
Issue Seem to Be IN WHERE Clause If column historydate Is Datetime Then Surely you will not get any record based on this WHERE Clause historydate >= '2017-01-01'
SELECT DISTINCT
cl.id AS id, cl.[KEY] AS issuekey,
MAX(historyDate) AS releaseDate,
m.issueType,
m.priority
FROM d_jira_changelog cl
JOIN d_jira_changelog_items ci ON ci.historyId = cl.historyId
JOIN d_jira_main m ON m.id = cl.id
WHERE(ci.changeitemfrom = 'Phase1'
AND ci.changeItemTo = 'Phase2')
AND changeItemField = 'status'
AND m.projectkey IN('ABC', 'CBA', 'XYZ', 'YOYO')
CONVERT(NVARCHAR,historydate,111) >= CONVERT(NVARCHAR,'2017-01-01',111)
GROUP BY cl."id", cl."key", m.issueType, m.priority;

Duplicate Values in SQL

I'm using this query and have used the Select Distinct code to enusre no duplicates are pulled from the database.
However on my QTD colum the number is sometimes X2 the proper amount?
This is probably an error with the server or would my query be incorrect?
SELECT DISTINCT ad.eid, MAX(u1.email) as ops,MAX(u2.email) as rep,
(SUM(ad.cost)) as qtd_spend,
Sum(case when day < current_date AND day >='2015-01-01' then cost else 0 end) as MTD,
AVG(case when day < current_date AND day >= current_date-7 then cost else null end) as weekly_spend
FROM adcube as ad
inner JOIN advertisables as a on ad.eid = a.eid
LEFT JOIN organizations as o on o.id = a.id
LEFT outer JOIN users as u1 on o.ops_organization_id = u1.organization_id
LEFT outer JOIN users as u2 on o.sales_organization_id = u2.organization_id
WHERE day >='2015-01-01' and day < current_date
GROUP BY eid
You must have GROUP BY if you have aggregate functions (such as SUM or MAX).
What is likely the problem is in you JOINs.
I am not familiar with your data structure, but I am assuming that in your advertisables table, it contains (or CAN contain) more than one entry of the same "eid" - is this correct? Or do you have a constraint?
If this is correct, then when you join even if you have only ONE entry in the "adcube" table, once it JOINs with the multiple entries in the "advertisables" table then it pulls up TWO records (or however many match) and then the aggregate results at the select level of the statement then sum BOTH (or more) columsn.
So you should take the duplicates out of hte joining tables or factor that into account.
EDIT:
Ok, well glad to know that is the problem. You will not fix it by INNER JOINING either. You will have to do an inline select statement.
The best way to solve this, from what I understand you are trying to do, is do the following:
SELECT ad.eid
, (
select max(u1.email)
from JOIN advertisables as a
LEFT JOIN organizations as o on o.id = a.id
LEFT outer JOIN users as u1 on o.ops_organization_id = u1.organization_id
LEFT outer JOIN users as u2 on o.sales_organization_id = u2.organization_id
where a.eid = ad.eid
) as ops
, (
select max(u2.email)
from JOIN advertisables as a
LEFT JOIN organizations as o on o.id = a.id
LEFT outer JOIN users as u1 on o.ops_organization_id = u1.organization_id
LEFT outer JOIN users as u2 on o.sales_organization_id = u2.organization_id
where a.eid = ad.eid
) as rep
, (SUM(ad.cost)) as qtd_spend
, Sum(case when day < current_date AND day >='2015-01-01' then cost else 0 end) as MTD
, AVG(case when day < current_date AND day >= current_date-7 then cost else null end) as weekly_spend
FROM adcube as ad
WHERE day >='2015-01-01' and day < current_date
GROUP BY eid

Inner join that ignore singlets

I have to do an self join on a table. I am trying to return a list of several columns to see how many of each type of drug test was performed on same day (MM/DD/YYYY) in which there were at least two tests done and at least one of which resulted in a result code of 'UN'.
I am joining other tables to get the information as below. The problem is I do not quite understand how to exclude someone who has a single result row in which they did have a 'UN' result on a day but did not have any other tests that day.
Query Results (Columns)
County, DrugTestID, ID, Name, CollectionDate, DrugTestType, Results, Count(DrugTestType)
I have several rows for ID 12345 which are correct. But ID 12346 is a single row of which is showing they had a row result of count (1). They had a result of 'UN' on this day but they did not have any other tests that day. I want to exclude this.
I tried the following query
select
c.desc as 'County',
dt.pid as 'PID',
dt.id as 'DrugTestID',
p.id as 'ID',
bio.FullName as 'Participant',
CONVERT(varchar, dt.CollectionDate, 101) as 'CollectionDate',
dtt.desc as 'Drug Test Type',
dt.result as Result,
COUNT(dt.dru_drug_test_type) as 'Count Of Test Type'
from
dbo.Test as dt with (nolock)
join dbo.History as h on dt.pid = h.id
join dbo.Participant as p on h.pid = p.id
join BioData as bio on bio.id = p.id
join County as c with (nolock) on p.CountyCode = c.code
join DrugTestType as dtt with (nolock) on dt.DrugTestType = dtt.code
inner join
(
select distinct
dt2.pid,
CONVERT(varchar, dt2.CollectionDate, 101) as 'CollectionDate'
from
dbo.DrugTest as dt2 with (nolock)
join dbo.History as h2 on dt2.pid = h2.id
join dbo.Participant as p2 on h2.pid = p2.id
where
dt2.result = 'UN'
and dt2.CollectionDate between '11-01-2011' and '10-31-2012'
and p2.DrugCourtType = 'AD'
) as derived
on dt.pid = derived.pid
and convert(varchar, dt.CollectionDate, 101) = convert(varchar, derived.CollectionDate, 101)
group by
c.desc, dt.pid, p.id, dt.id, bio.fullname, dt.CollectionDate, dtt.desc, dt.result
order by
c.desc ASC, Participant ASC, dt.CollectionDate ASC
This is a little complicated because the your query has a separate row for each test. You need to use window/analytic functions to get the information you want. These allow you to do calculate aggregation functions, but to put the values on each line.
The following query starts with your query. It then calculates the number of UN results on each date for each participant and the total number of tests. It applies the appropriate filter to get what you want:
with base as (<your query here>)
select b.*
from (select b.*,
sum(isUN) over (partition by Participant, CollectionDate) as NumUNs,
count(*) over (partition by Partitipant, CollectionDate) as NumTests
from (select b.*,
(case when result = 'UN' then 1 else 0 end) as IsUN
from base
) b
) b
where NumUNs <> 1 or NumTests <> 1
Without the with clause or window functions, you can create a particularly ugly query to do the same thing:
select b.*
from (<your query>) b join
(select Participant, CollectionDate, count(*) as NumTests,
sum(case when result = 'UN' then 1 else 0 end) as NumUNs
from (<your query>) b
group by Participant, CollectionDate
) bsum
on b.Participant = bsum.Participant and
b.CollectionDate = bsum.CollectionDate
where NumUNs <> 1 or NumTests <> 1
If I understand the problem, the basic pattern for this sort of query is simply to include negating or exclusionary conditions in your join. I.E., self-join where columnA matches, but columns B and C do not:
select
[columns]
from
table t1
join table t2 on (
t1.NonPkId = t2.NonPkId
and t1.PkId != t2.PkId
and t1.category != t2.category
)
Put the conditions in the WHERE clause if it benchmarks better:
select
[columns]
from
table t1
join table t2 on (
t1.NonPkId = t2.NonPkId
)
where
t1.PkId != t2.PkId
and t1.category != t2.category
And it's often easiest to start with the self-join, treating it as a "base table" on which to join all related information:
select
[columns]
from
(select
[columns]
from
table t1
join table t2 on (
t1.NonPkId = t2.NonPkId
)
where
t1.PkId != t2.PkId
and t1.category != t2.category
) bt
join [othertable] on (<whatever>)
join [othertable] on (<whatever>)
join [othertable] on (<whatever>)
This can allow you to focus on getting that self-join right, without interference from other tables.