null result for average number of days by month - sql

select a.clientid, a.CaseType, b.EnrollmentStartDate, a.EligibilityStartDate, datediff(day, a.EligibilityStartDate, b.EnrollmentStartDate) as date_diff
INTO ##temptable1
FROM dbo.Client a, dbo.ClientEnrollment b
WHERE a.ClientId = b.ClientId
AND a.CaseType = 99
ORDER BY a.ClientId
select avg (date_diff) from ##temptable1
so the above query gives me the overall average number of days it takes for a client to enroll into a program from their eligibility start date. I now want to sort the results by each month
select avg (date_diff) from ##temptable1
where EligibilityStartDate = '2019-03-01
for some reason I'm getting NULL no matter what date I specify ( even though the original query produces over 40k results ) I've tried inserting EligibilityStartDate = '2019-03-01' into the table itself but that did not work either.

Presumably, you want something like this:
SELECT YEAR(c.EligibilityStartDate) as yyyy,
MONTH(c.EligibilityStartDate) as mm,
AVG(DATEDIFF(DAY, c.EligibilityStartDate, ce.EnrollmentStartDate) as date_diff
FROM dbo.Client c JOIN
dbo.ClientEnrollment ce
ON c.ClientId = ce.ClientId AND c.CaseType = 99
GROUP BY YEAR(c.EligibilityStartDate), MONTH(c.EligibilityStartDate)
ORDER BY YEAR(c.EligibilityStartDate), MONTH(c.EligibilityStartDate);
Notes:
Never use commas in the FROM clause.
Always use proper, explicit, standard JOIN syntax.
Use meaningful table aliases (i.e. abbreviations of table names) rather than meaningless ones.
You seem to want an aggregation query.

Related

Group by function in sql

It is throwing a error for the group by function. how do i fix it
SELECT TO_CHAR(TRANSBDATE,'MON-YYYY')PERIOD,B.CURCODE,COUNT(DISTINCT CUSTOMERID) UNIQUECUSTOMERS,COUNT(CURCODE)TRANS
FROM FX_TRANSHEADER A,FX_TRANSDETAIL B
WHERE A.TRANSNO = B.TRANSNO AND A.TRANSBDATE BETWEEN '01-JAN-2018' AND '30-JUN-2019' AND C_IDTYPE NOT IN ('CR')
ORDER BY 1 , 4
GROUP BY TO_CHAR(TRANSBDATE,'MON-YYYY')PERIOD,COUNT(DISTINCT CUSTOMERID),COUNT(CURCODE)
The GROUP BY only needs the fields on which you want to aggregate:
GROUP BY TO_CHAR(TRANSBDATE,'MON-YYYY')PERIOD, B.CURCODE
So not on COUNT(B.CURCODE) but on CURCODE
SELECT TO_CHAR(TRANSBDATE,'MON-YYYY')PERIOD,B.CURCODE,COUNT(DISTINCT CUSTOMERID) UNIQUECUSTOMERS,COUNT(CURCODE)TRANS
FROM FX_TRANSHEADER A,FX_TRANSDETAIL B
WHERE A.TRANSNO = B.TRANSNO AND A.TRANSBDATE BETWEEN '01-JAN-2018' AND '30-JUN-2019' AND C_IDTYPE NOT IN ('CR')
GROUP BY TO_CHAR(TRANSBDATE,'MON-YYYY'),B.CURCODE
ORDER BY 1 , 4
You cannot include aggregation functions in the GROUP BY. You only want the unaggregated columns from the SELECT.
I would recommend writing the query as:
SELECT TO_CHAR(H.TRANSBDATE,'MON-YYYY') as PERIOD,
D.CURCODE,
COUNT(DISTINCT ?.CUSTOMERID) as UNIQUECUSTOMERS,
COUNT(*) as TRANS
FROM FX_TRANSHEADER H JOIN
FX_TRANSDETAIL D
ON H.TRANSNO = D.TRANSNO
WHERE H.TRANSBDATE >= DATE '2018-01-01' AND
H.TRANSBDATE < DATE '2018-07-01' AND
?.C_IDTYPE NOT IN ('CR')
ORDER BY 1 , 4
GROUP BY TO_CHAR(H.TRANSBDATE, 'MON-YYYY');
The ? is for the column aliases for the tables that have the specified columns.
Notes:
Never use commas in the FROM clause. Always use proper, explicit, standard JOIN syntax.
Use meaningful table aliases (table abbreviations) rather than arbitrary letters.
Use DATE to represent date literals, so your code is not tied to particular internationalization settings on your server.
Replaced BETWEEN with two direct comparisons. This is particularly important in databases such as Oracle, where the DATE data type has a time component.

Sum certain rows in sql

I want to sum different rows of my table into a different column. I have a Id column which have multiple times. When I try to sum the time table it says cannot sum time data type.
Here is what my query looks like atm:
select t.Id,
a.EndTime,
cast(A.Endtime as time)[time]
from [plugin.tickets].Ticket as T
join
[plugin.tickets].TicketActivity as TA ON TA.TicketId = T.Id
join
dbo.Activity as A on A.Id = TA.ActivityId
Here is the output of this query:
As you can see there are id numbers which have multiple times. How can I sum these values?
EDIT:
I have changed my query as following:
select t.Id
,a.EndTime
,convert (varchar(5), EndTime,108) as Tijd
from [plugin.tickets].Ticket as T
join
[plugin.tickets].TicketActivity as TA ON TA.TicketId = T.Id
join
dbo.Activity as A on A.Id = TA.ActivityId
I just want to sum these where the ID number is the same.
Thanks,
Shabby
You should look into the two functions DATEPART and DATEADD. I'm assuming your useing T-SQL here. So you would take the time field convert that to hour which would give you 17 for example and then use date add on the End Time field.
https://learn.microsoft.com/en-us/sql/t-sql/functions/datepart-transact-sql?view=sql-server-2017

postgresql Select date from min value

I want to select list of people, who have FIRST time 'E' diagnosis from 2016-01-01.
my code looks like
SELECT DISTINCT ON(form25.visit.patient_id )
form25.visit.patient_id,
CONCAT(demographics.party.firstname,' ', demographics.party.lastname) AS pacientas,
form25.visit.disease_code,
demographics.party.code,
form25.visit.date,
form25.diagnose.disease_type
FROM form25.visit
JOIN demographics.party
ON form25.visit.patient_id = demographics.party.id
JOIN form25.diagnose
ON form25.visit.patient_id = form25.diagnose.card_id
WHERE form25.visit.disease_code LIKE 'E%'
AND form25.diagnose.disease_type = '+'
AND form25.visit.date >= '2016-01-01'
ORDER BY form25.visit.patient_id, form25.visit.date ASC
result i get:
patients E.. 2013,2014,2016, 2017
(contains E.. with 2016 so I see them)
All I want is to eliminate those who have date(s) with E.. before 2016, and see only those who had it first time from 2016.
First, your query would be much easier to read (and write) if you used table aliases.
Second, you can get what you want by doing an aggregation and then looking at the minimum date:
SELECT v.patient_id, CONCAT(p.firstname, ' ', p.lastname) AS pacientas,
MIN(v.date) as first_date
FROM form25.visit v JOIN
demographics.party p
ON v.patient_id = p.id JOIN
form25.diagnose d
ON v.patient_id = d.card_id
WHERE v.disease_code LIKE 'E%' AND d.disease_type = '+'
GROUP BY patient_id, pacientas
HAVING MIN(v.date) >= '2016-01-01';
Note that this gives you the patients that meet the conditions. If you need visit details, you can join back or use window functions.

Unpivot date columns to a single column of a complex query in Oracle

Hi guys, I am stuck with a stubborn problem which I am unable to solve. Am trying to compile a report wherein all the dates coming from different tables would need to come into a single date field in the report. Ofcourse, the max or the most recent date from all these date columns needs to be added to the single date column for the report. I have multiple users of multiple branches/courses for whom the report would be generated.
There are multiple blogs and the latest date w.r.t to the blogtitle needs to be grouped, i.e. max(date_value) from the six date columns should give the greatest or latest date for that blogtitle.
Expected Result:
select u.batch_uid as ext_person_key, u.user_id, cm.batch_uid as ext_crs_key, cm.crs_id, ir.role_id as
insti_role, (CASE when b.JOURNAL_IND = 'N' then
'BLOG' else 'JOURNAL' end) as item_type, gm.title as item_name, gm.disp_title as ITEM_DISP_NAME, be.blog_pk1 as be_blogPk1, bc.blog_entry_pk1 as bc_blog_entry_pk1,bc.pk1,
b.ENTRY_mod_DATE as b_ENTRY_mod_DATE ,b.CMT_mod_DATE as BlogCmtModDate, be.CMT_mod_DATE as be_cmnt_mod_Date,
b.UPDATE_DATE as BlogUpDate, be.UPDATE_DATE as be_UPDATE_DATE,
bc.creation_date as bc_creation_date,
be.CREATOR_USER_ID as be_CREATOR_USER_ID , bc.creator_user_id as bc_creator_user_id,
b.TITLE as BlogTitle, be.TITLE as be_TITLE,
be.DESCRIPTION as be_DESCRIPTION, bc.DESCRIPTION as bc_DESCRIPTION
FROM users u
INNER JOIN insti_roles ir on u.insti_roles_pk1 = ir.pk1
INNER JOIN crs_users cu ON u.pk1 = cu.users_pk1
INNER JOIN crs_mast cm on cu.crsmast_pk1 = cm.pk1
INNER JOIN blogs b on b.crsmast_pk1 = cm.pk1
INNER JOIN blog_entry be on b.pk1=be.blog_pk1 AND be.creator_user_id = cu.pk1
LEFT JOIN blog_CMT bc on be.pk1=bc.blog_entry_pk1 and bc.CREATOR_USER_ID=cu.pk1
JOIN gradeledger_mast gm ON gm.crsmast_pk1 = cm.pk1 and b.grade_handler = gm.linkId
WHERE cu.ROLE='S' AND BE.STATUS='2' AND B.ALLOW_GRADING='Y' AND u.row_status='0'
AND u.available_ind ='Y' and cm.row_status='0' and and u.batch_uid='userA_157'
I am getting a resultset for the above query with multiple date columns which I want > > to input into a single columnn. The dates have to be the most recent, i.e. max of the dates in the date columns.
I have successfully done the Unpivot by using a view to store the above
resultset and put all the dates in one column. However, I do not
want to use a view or a table to store the resultset and then do
Unipivot simply because I cannot keep creating views for every user
one would query for.
The max(date_value) from the date columns need to be put in one single column. They are as follows:
* 1) b.entry_mod_date, 2) b.cmt_mod_date ,3) be.cmt_mod_date , 4) b.update_Date ,5) be.update_date, 6) bc.creation_date *
Apologies that I could not provide the desc of all the tables and the
fields being used.
Any help to get the above mentioned max of the dates from these
multiple date columns into a single column without using a view or a
table would be greatly appreciated.*
It is not clear what results you want, but the easiest solution is to use greatest().
with t as (
YOURQUERYHERE
)
select t.*,
greatest(entry_mod_date, cmt_mod_date, cmt_mod_date, update_Date,
update_date, bc.creation_date
) as greatestdate
from t;
select <columns>,
case
when greatest (b_ENTRY_mod_DATE) >= greatest (BlogCmtModDate) and greatest(b_ENTRY_mod_DATE) >= greatest(BlogUpDate)
then greatest( b_ENTRY_mod_DATE )
--<same implementation to compare each time BlogCmtModDate and BlogUpDate separately to get the greatest then 'date'>
,<columns>
FROM table
<rest of the query>
UNION ALL
Select <columns>,
case
when greatest (be_cmnt_mod_Date) >= greatest (be_UPDATE_DATE)
then greatest( be_cmnt_mod_Date )
when greatest (be_UPDATE_DATE) >= greatest (be_cmnt_mod_Date)
then greatest( be_UPDATE_DATE )
,<columns>
FROM table
<rest of the query>
UNION ALL
Select <columns>,
GREATEST(bc_creation_date)
,<columns>
FROM table
<rest of the query>

Trying to select multiple columns on an inner join query with group and where clauses

I'm trying to run a query where it will give me one Sum Function, then select two columns from a joined table and then to group that data by the unique id i gave them. This is my original query and it works.
SELECT Sum (Commission_Paid)
FROM [INTERN_DB2].[dbo].[PaymentList]
INNER JOIN [INTERN_DB2]..[RealEstateAgentList]
ON RealEstateAgentList.AgentID = PaymentList.AgentID
WHERE Close_Date >= '1/1/2013' AND Close_Date <= '12/31/2013'
GROUP BY RealEstateAgentList.AgentID
I've tried the query below, but I keep getting an error and I don't know why. It says its a syntax error.
SELECT Sum (Commission_Paid)
FROM [INTERN_DB2].[dbo].[PaymentList]
INNERJOIN [INTERN_DB2]..[RealEstateAgentList](
Select First_Name, Last_Name
From [Intern_DB2]..[RealEstateAgentList]
Group By Last_name
)
ON RealEstateAgentList.AgentID = PaymentList.AgentID
WHERE Close_Date >= '1/1/2013' AND Close_Date <= '12/31/2013'
GROUP BY RealEstateAgentList.AgentID
Your query has multiple problems:
SELECT rl.AgentId, rl.first_name, rl.last_name, Sum(Commission_Paid)
FROM [INTERN_DB2].[dbo].[PaymentList] pl inner join
(Select agent_id, min(first_name) as first_name, min(last_name) as last_name
From [Intern_DB2]..[RealEstateAgentList]
GROUP BY agent_id
) rl
ON rl.AgentID = pl.AgentID
WHERE Close_Date >= '2013-01-01' AND Close_Date <= '2013-12-31'
GROUP BY rl.AgentID, rl.first_name, rl.last_name;
Here are some changes:
INNERJOIN --> inner join.
Fixed the syntax of the subquery next to the table name.
Removed columns for first and last name. They are not used.
Changed the subquery to include agent_id.
Added agent_id, first_name, and last_name to the outer aggregation, so you can tell where the values are coming from.
Changed the date formats to a less ambiguous standard form.
Added table alias for subquery.
I suspect the subquery on the agent list is not important. You can probably do:
SELECT rl.AgentId, rl.first_name, rl.last_name, Sum(pl.Commission_Paid)
FROM [INTERN_DB2].[dbo].[PaymentList] pl inner join
[Intern_DB2]..[RealEstateAgentList] rl
ON rl.AgentID = pl.AgentID
WHERE pl.Close_Date >= '2013-01-01' AND pl.Close_Date <= '2013-12-31'
GROUP BY rl.AgentID, rl.first_name, rl.last_name;
EDIT:
I'm glad this solution helped. As you continue to write queries, try to always do the following:
Use table aliases that are abbreviations of the table names.
Always use table aliases when referring to columns.
When using date constants, either use "YYYY-MM-DD" format or use convert() to convert a string using the specified format. (The latter is actually the safer method, but the former is more convenient and works in almost all databases.)
Pay attention to the error messages; they can be informative in SQL Server (unfortunately, other databases are not so clear).
Format your query so other people can understand it. This will help you understand and debug your queries as well. I have a very particular formatting style (which no one is going to change at this point); the important thing is not the particular style but being able to "see" what the query is doing. My style is documented in my book "Data Analysis Using SQL and Excel.
There are other rules, but these are a good way to get started.
SELECT Sum (Commission_Paid)
FROM [INTERN_DB2].[dbo].[PaymentList] pl
INNER JOIN (
Select First_Name, Last_Name
From [Intern_DB2]..[RealEstateAgentList]
Group By Last_name
) x ON x.AgentID = pl.AgentID
WHERE Close_Date >= '1/1/2013'
AND Close_Date <= '12/31/2013'
GROUP BY RealEstateAgentList.AgentID
This is how the query should look... however, if you subquery first and last name, you'll also have to include them in the group by. Assuming Close_Date is in the PaymentList table, this is how I would write the query:
SELECT
al.AgentID,
al.FirstName,
al.LastName,
Sum(pl.Commission_Paid) AS Commission_Paid
FROM [INTERN_DB2].[dbo].[PaymentList] pl
INNER JOIN [Intern_DB2].dbo.[RealEstateAgentList] al ON al.AgentID = pl.AgentID
WHERE YEAR(pl.Close_Date) = '2013'
GROUP BY al.AgentID, al.FirstName, al.LastName
Subqueries are evil, for the most part. There's no need for one here, because you can just get the columns from the join.