I've got a sql select query which returns two rows:
SELECT contacts_patientcontact.contact_id, patient_firstname, recent_mailouts
FROM contacts_patientcontact
INNER JOIN patients_patientcore
ON contacts_patientcontact.patient_id = patients_patientcore.patient_id
LEFT JOIN (SELECT contact_id, COUNT(*) as recent_mailouts
FROM contacts_communicationinstance
WHERE communication_type = 'questionnaire mailout'
GROUP BY contact_id) mail_outs
ON contacts_patientcontact.contact_id = mail_outs.contact_id
WHERE contact_date BETWEEN '2012/03/05' AND '2012/03/12'
AND contact_type = 'Postal Questionnaire'
AND patient_dead != 1
AND consent_withdrawn IS NULL
AND lost_follow_up != 1
AND (key = 'A' OR key = 'C')
AND (recent_mailouts < 1
OR recent_mailouts IS NULL);
However when I add it into django using the raw method the queryset doesn't seem to be iterable.
def weekly_questionnaire_mailout_query(monday):
"""
Returns a query set of PatientContact objects for patients
due a mailout in the week following the parameter 'monday'.
"""
nxt_monday = monday + datetime.timedelta(weeks=1)
nxt_monday_str = nxt_monday.strftime('%Y/%m/%d')
monday_str = monday.strftime('%Y/%m/%d')
contacts = PatientContact.objects.raw("""
SELECT contacts_patientcontact.contact_id
FROM contacts_patientcontact
INNER JOIN patients_patientcore
ON contacts_patientcontact.patient_id = patients_patientcore.patient_id
LEFT JOIN (SELECT contact_id, COUNT(*) as recent_mailouts
FROM contacts_communicationinstance
WHERE communication_type = 'questionnaire mailout'
GROUP BY contact_id) mail_outs
ON contacts_patientcontact.contact_id = mail_outs.contact_id
WHERE contact_date BETWEEN '%s' AND '%s'
AND contact_type = 'Postal Questionnaire'
AND patient_dead != 1
AND consent_withdrawn IS NULL
AND lost_follow_up != 1
AND (cora = 'A' OR cora = 'C')
AND (recent_mailouts < 1
OR recent_mailouts IS NULL);
""" % (monday_str, nxt_monday_str)
)
return contacts
contacts = weekly_questionnaire_mailout_query(monday)
for contact in contacts:
patients.add(contact.patient_id)
That last line is never reached. (I've checked the dates are correct, and I've included the PatientContact model below).
class PatientContact(models.Model):
contact_id = models.AutoField(primary_key=True)
patient_id = models.ForeignKey(PatientCore, db_column="patient_id",
verbose_name="patient")
# additional fields..
I'm at a loss with this - instead of showing the items in a queryset my (pydevd) debugger shows a RawQuerySet object. The same function (with the same parameter) is returning an object that djangotables2 handles fine (producing the table I'd expect from the sql output).
EDIT
That's embarrassing - it was the dates after all - I wasn't actually running the same SQL query (I thought I'd checked and rechecked them last week). Apologies to anyone who's spent any time on this.
This was a mistake. I was running the wrong piece of code.
The solution is to be more carefull!
Related
Elon Reeve Musk FRS is an entrepreneur and business magnate. He is the founder, CEO, and Chief Engineer at SpaceX; early-stage investor, CEO, and Product Architect of Tesla, Inc.; founder of The Boring Company; and co-founder of Neuralink and OpenAI.
Your inner select returns a table. That can't be used as parameter to match a WHERE IN condition. Instead try using an INNER JOIN
sum(decode(
select sum(dou.noukn)
from dou
join v_kzeiritsu on
dou.zeiritsu = v_kzeiritsu.zeiritsu
)) as noukn2;
Just move your sum logic inside select as follows:
(SELECT SUM(DOU$2.NOUKN)
FROM SDNISHI.V_KZEIRITSU V
WHERE DOU$2.ZEIRITSU = V.ZEIRITSU) AS NOUKN2
In case If it gives aggregation error then use sum(above query) AS NOUKN2
Your code is very strange. For instance, it seems to assume that V_KZEIRITSU has one row. But, you can move this to the FROM clause:
SELECT SUM(CASE WHEN DOU.ZEIRITSU = K.ZEIRITSU THEN DOU.NOUKN ELSE 0 END) AS NOUKN2
FROM DOU LEFT JOIN
V_KZEIRITSU K
ON 1=1 -- in case the table is really empty
A slightly more reasonable version would be:
SELECT SUM(DOU.NOUKN) AS NOUKN2
FROM DOU LEFT JOIN
V_KZEIRITSU K
ON DOU.ZEIRITSU = K.ZEIRITSU -- in case the table is really empty
It seems rather unlikely to me that this is what you really intend. If not, I would suggest that you ask a new question with appropriate same data, desired results, and explanation of the results. A non-working query should not be expected to provide the same level of information.
I'd say that it is, actually, as simple as
select sum(dou.noukn)
from dou
where dou.zeiritsu in (select zeiritsu from v_kzeiritsu)
(I'm not sure what dou is (table? alias?), but I hope you do.)
After you edited the question, I'm editing the answer. I marked with "--> this" two lines that - in my opinion - might help. As previously, the whole sum(case ...) as noukn2 is replaced by a simple sum(dou$2.noukn).
Note that - in Oracle - you can't use as keyword for table alias. For example:
no: from employees as e
yes: from employees e
Here's your query:
SELECT DOU$2.CUSTCD AS CUSTCD,
DOU$2.CHUNO AS CHUNO,
DOU$2.LINNO AS LINNO,
DOU$2.SHIPDAYYM AS SHIPDAYYM,
SUM (DOU$2.NOUKN) AS NOUKN,
SUM (DOU$2.ZEIKN) AS ZEIKN,
SUM (dou$2.noukn) AS noukn2 --> this
FROM SDNISHI.T_HCHUMON_DOUSOU DOU$2
INNER JOIN SDNISHI.SY_KANRI KNR ON KNR.SHIPDAYYM = DOU$2.SHIPDAYYM
INNER JOIN SDNISHI.T_HCHUMON_MEI MEI
ON MEI.CUSTCD = DOU$2.CUSTCD
AND MEI.CHUNO = DOU$2.CHUNO
AND MEI.LINNO = DOU$2.LINNO
AND MEI.SHIPDAYYM = DOU$2.SHIPDAYYM
AND MEI.USEDNGKBN = '0'
AND MEI.CANCELKBN = '0'
LEFT OUTER JOIN SDNISHI.T_HCHUMON_HD HD
ON HD.CUSTCD = MEI.CUSTCD
AND HD.CHUNO = MEI.CHUNO
AND HD.LINNO = MEI.LINNO
AND HD.USEDNGKBN = '0'
AND HD.CANCELKBN = '0'
AND isnull (HD.CANKBN, '00') = '00'
JOIN v_keziritsu vk ON vk.zeiritsu = dou$2.zeiritsu --> this
WHERE DOU$2.USEDNGKBN = '0'
AND DOU$2.CANCELKBN = '0'
AND ( ( MEI.CHGDELKBN = '1'
AND MEI.HDOUSOUKBN = '02'
AND ( MEI.CHUSU > 0
OR MEI.BCHUSU > 0))
OR ( MEI.CHGDELKBN != '1'
AND HD.HDOUSOUKBN = '02'
AND ( MEI.CHKBTNFGA = '1'
AND HD.CHUSU > 0)
OR ( MEI.CHKBTNFGB = '1'
AND HD.BCHUSU > 0)))
GROUP BY DOU$2.CUSTCD,
DOU$2.CHUNO,
DOU$2.LINNO,
DOU$2.SHIPDAYYM
I got verry strange problem with dql.
I have two tables connecter with foreign key:
== Table incident ==
id, cycle_nr, ...
1, 1
2, 3
== Table incident_active ==
id, incident_id, user_id, ...
1, 1, 1
...
I need to show active incidents for some cycles and everything is fine if I do mySQL query lilke this:
SELECT * FROM `incident_active` LEFT JOIN incident ON incident.id = `incident_active`.incident_id WHERE cycle_nr <= 2 and user_id = 1
Same query in DQL works too, but only for cycle_nr != 2
SELECT incidentActive, incident
FROM AccountingBundle:IncidentActive incidentActive
JOIN incidentActive.incident incident
WHERE incidentActive.company_id = 1 AND incident.cycle_nr <= 2
For cycle_nr <= 2 i get an empty result. I guess because of the abscense of incident for this cycle, but I'm asking <=2 and not == 2. Any Ideas?
The default join in DQL is INNER JOIN. Those queries are not equivalent.
SELECT * FROM `incident_active`
LEFT JOIN incident ON incident.id = `incident_active`.incident_id
WHERE cycle_nr <= 2 and user_id = 1
This SQL query is written in DQL like this (assuming the user is an entity)
SELECT incidentActive, incident
FROM AccountingBundle:IncidentActive incidentActive
LEFT JOIN incidentActive.incident incident
WHERE incident.cycle_nr <= :cycleNr
AND incidentActive.user = :userId
Also, when you have conditions just for the join and don't want it to affect the results from "main" table, you should add them to that join conditions only, like this.
SELECT incidentActive, incident
FROM AccountingBundle:IncidentActive incidentActive
LEFT JOIN incidentActive.incident incident WITH incident.cycle_nr <= :cycleNr
WHERE incidentActive.user = :userId
With bound parameters it should look like this, given the above query is in $dql.
$result = $em->createQuery($dql)
->setParameter('cycleNr', 2)
->setParameter('userId', 1)
->getResult();
I have a query with subqueries in the where statement which works fine but I need to improve on it but I am not sure of the best way to go about this.
Basically I am getting last years results for students in this years classes. The code below works fine for classcode '10DRADRA1' but there are many more classes and I want the query to iterate through all classes for 2017 Semester 1. I need to have the classcode included as one of the output fields also. So the query will start with the first class and give all the results for that class, then do the same for the next class in the subquery. I am not sure how to include the classcode in the select statement next to all the results from the previous year.
Note that students may do a number of classes this year so there may be some repetition of the results from the previous year. Every class they do this year should include the students name and their results from the previous year. I hardcoded '10DRADRA1' in just to get things working, if I remove it it provides all students in the school only once, while I want each class they are in once and the same results for every class they are in.
Also not that vStudentReportsSemesterResults is a view that holds all results, StudentClasses is a table which holds the class codes a student is doing and SubjectClasses is a table holding the codes for all classes in the school
Is anyone able to advise on the best way of doing this? Here is my current code.
SELECT vStudentReportsSemesterResults.StudentID,
vStudentReportsSemesterResults.AssessResultsResult,
vStudentReportsSemesterResults.AssessAreaHdgAbbrev2,
vStudentReportsSemesterResults.FileSemester,
vStudentReportsSemesterResults.FileYear,
vStudentReportsSemesterResults.ClassLearningAreaCode,
vStudentReportsSemesterResults.AssessmentCode,
vStudentReportsSemesterResults.StudentNameInternal
FROM vStudentReportsSemesterResults
WHERE vStudentReportsSemesterResults.StudentID in
(
select StudentClasses.ID from StudentClasses
where StudentClasses.filesemester = 1 and
StudentClasses.fileyear = 2017 and
StudentClasses.classcode in
(
select SubjectClasses.ClassCode from SubjectClasses
where SubjectClasses.FileYear = 2017 and
SubjectClasses.FileSemester = 1 and
SubjectClasses.FileType = 'A' and
SubjectClasses.ClassCampus = 'S' and
SubjectClasses.ClassCode like '10DRADRA1'
)
)
and (vStudentReportsSemesterResults.ClassLearningAreaCode = 'ENG' OR
vStudentReportsSemesterResults.ClassLearningAreaCode = 'MAT' OR
vStudentReportsSemesterResults.ClassLearningAreaCode = 'SCI') AND
(vStudentReportsSemesterResults.AssessAreaHdgAbbrev2 = 'Grade' OR
vStudentReportsSemesterResults.AssessAreaHdgAbbrev2 = 'Level') AND
(vStudentReportsSemesterResults.AssessResultsResult <> '') AND
(vStudentReportsSemesterResults.FileYear = 2016) AND
(vStudentReportsSemesterResults.FileSemester = 4)
Join StudentClasses to vStudentReportsSemesterResults:
SELECT
sc.ClassCode,
srsr.StudentID,
srsr.AssessResultsResult,
srsr.AssessAreaHdgAbbrev2,
srsr.FileSemester,
srsr.FileYear,
srsr.ClassLearningAreaCode,
srsr.AssessmentCode,
srsr.StudentNameInternal
FROM vStudentReportsSemesterResults srsr
JOIN StudentClasses sc
ON sc.ID = srsr.StudentID
AND sc.FileSemester = 1
AND sc.FileYear = srsr.FileYear + 1
AND EXISTS
(
select *
from SubjectClasses subc
where subc.FileYear = sc.FileYear
and subc.ClassCode = sc.ClassCode
and subc.FileSemester = sc.FileSemester
and subc.FileType = 'A'
and subc.ClassCampus = 'S'
)
WHERE srsr.ClassLearningAreaCode in ('ENG', 'MAT', 'SCI')
AND srsr.AssessAreaHdgAbbrev2 in ('Grade', 'Level')
AND srsr.AssessResultsResult <> ''
AND srsr.FileYear = 2016
AND srsr.FileSemester = 4;
This is more readable:
SELECT
ClassCode,
StudentID,
AssessResultsResult,
AssessAreaHdgAbbrev2,
ClassLearningAreaCode,
AssessmentCode,
StudentNameInternal,
lr.FileYear,
lr.FileSemester,
tr.FileYear,
tr.FileSemester,
tr.FileType,
tr.ClassCampus
FROM
vStudentReportsSemesterResults lr
inner join (
select ID, sc.ClassCode, sc.FileYear, sc.filesemester, sbjc.FileType, sbjc.ClassCampus
from StudentClasses sc
INNER JOIN SubjectClasses sbjc ON SC.classcode = sbjc.ClassCode and sc.FileSemester=sbjc.FileSemester and sc.FileYear=sbjc.FileYear
) tr on lr.StudentID = tr.ID
and lr.FileYear = tr.FileYear - 1
WHERE
ClassLearningAreaCode IN ('ENG', 'MAT', 'SCI')
AND AssessAreaHdgAbbrev2 IN ('Grade', 'Level')
AND (AssessResultsResult <> '')
AND lr.FileYear = 2016
AND lr.FileSemester = 4
and tr.FileSemester = 1
and tr.FileType = 'A'
and tr.ClassCampus = 'S'
ORDER BY 2,1,5
In SELECT section I have added some fields to better understand result.
In WHERE clause you can control how to filter comparision.
Put some indexes on join and filter columns and the query will run fast
I have a project in which I need to save request for file. I have to save the state of the request with the date of each step.
I have two tables in my database :
FileRequest :
FileRequestStatus :
I would like to create a request to get each FileName from the table FileRequest having only the Status == 'NEW'. The desired output would be in this case C12345, LIVE.
If you have a better idea in order to build my database, I'll take it
I tried something like that :
SELECT [FileName] FROM [FileRequest]
INNER JOIN [FileRequestStatus] ON [FileRequestStatus].[RequestId] = [FileRequest].[RequestId]
GROUP BY [FileRequestStatus].[RequestId]
HAVING COUNT([FileRequestStatus].[RequestStatus]) < 2
SELECT FR.FileName
FROM [FileRequest] FR
INNER JOIN [FileRequestStatus] FRS ON FRS.[RequestId] = FR.[RequestId]
GROUP BY FR.FileName
HAVING COUNT(CASE WHEN FRS.RequestStatus <> 'New' THEN 1 END) = 0 --No statuses other than `NEW`
AND COUNT(CASE WHEN FRS.RequestStatus = 'New' THEN 1 END) >= 1 --Atleast one status `NEW`
I think the simplest method is aggregation:
select fr.FileName
from nep.FileRequest fr join
nep.FileRequestStatus] frs
on frs.RequestId = fr.RequestId
group by fr.FileName
having min(frs.RequestStatus) = max(frs.RequestStatus) and
min(frs.RequestStatus) = 'New';
Note: This assumes that the request status is never NULL (although that is easy to take into account).
What this does is aggregate by file name and then check that the statuses for a given file are all equal (the first condition) and equal to 'New' (the second condition).
You need to include [FileName] to your GROUP BY, then you can select it in result
SELECT [nep].[FileRequest].[FileName] FROM [nep].[FileRequest]
INNER JOIN [nep].[FileRequestStatus] ON [nep].[FileRequestStatus].[RequestId] = [nep].[FileRequest].[RequestId]
GROUP BY [nep].[FileRequestStatus].[RequestId], [nep].[FileRequest].[FileName]
HAVING COUNT([nep].[FileRequestStatus].[RequestStatus]) < 2
We had an issue where our workflows have not been creating activities.
I now need to report which accounts have not had their workflows invoked.
I've tried advanced find and then moved to sql.
My question is can someone provide a simple starter query to pull which 'entity' has NOT had a specific activity associated with it?
Please let me know if the question is not clear enough or more info, is needed.
Below is a solution using SQL where I step through my thought process, and below that is a solution that gets started with the C# API (edit: just realized this is for a report, so that part can be disregarded). I've commented in most places, so I hope my methods are fairly straightforward.
SQL
1.
--get all the entities that aren't activities and aren't intersect entities (N:N tables)
--Put in your own where conditions to further filter this list,
--which is still probably far too expansive
SELECT
A.name EntityName
FROM MetadataSchema.Entity A
WHERE
A.IsActivity = 0
AND A.IsIntersect = 0
2.
--CROSS JOIN the non-activity entities with the activity entities
--to get a list of all possible entity/activity pairings
SELECT DISTINCT
A.name EntityName
, B.Name ActivityName
FROM MetadataSchema.Entity A
CROSS JOIN MetadataSchema.Entity B
WHERE
A.IsActivity = 0
AND A.IsIntersect = 0
AND B.IsActivity = 1
3.
--LEFT JOIN the partial cartesian join above against the Activity table,
--making a note of which entities actually have activity records.
--This will provide a complete list of which entity/activity pairings
--exist and don't exist
SELECT
A.name EntityName
, B.Name ActivityName
--if there is a matching activity, the unique key,
--ActivityTypeCode (int), will be positive.
--So, if there is a positive sum for an entity/activity
--pairing, you know there is a valid pair; otherwise
--no pair
, CAST(CASE WHEN sum(coalesce(C.ActivityTypeCode, 0)) > 0
THEN 1
ELSE 0
END AS BIT) EntityOwnsActivity
FROM MetadataSchema.Entity A
CROSS JOIN MetadataSchema.Entity B
LEFT JOIN dbo.ActivityPointer C ON
--ObjectTypeCode is a unique identifier for Entities;
--RegardingObjectTypeCode is the code for the entity type
--associated with a particular activity
A.ObjectTypeCode = C.RegardingObjectTypeCode
--ActivityTypeCode is the code for the particular activity
AND B.ObjectTypeCode = C.ActivityTypeCode
WHERE
A.IsActivity = 0
AND A.IsIntersect = 0
AND B.IsActivity = 1
GROUP BY
A.name
, B.Name
4.
--Putting it all together, using the above master table,
--filter out the entities/activities you're interested in
--(in this case, all entities that aren't associated with
--any emails)
SELECT
EntityName
FROM
(
SELECT
A.name EntityName
, B.Name ActivityName
, CAST(CASE WHEN sum(coalesce(C.ActivityTypeCode, 0)) > 0
THEN 1
ELSE 0
END AS BIT) EntityOwnsActivity
FROM MetadataSchema.Entity A
CROSS JOIN MetadataSchema.Entity B
LEFT JOIN dbo.ActivityPointer C ON
A.ObjectTypeCode = C.RegardingObjectTypeCode
AND B.ObjectTypeCode = C.ActivityTypeCode
WHERE
A.IsActivity = 0
AND A.IsIntersect = 0
AND B.IsActivity = 1
GROUP BY
A.name
, B.Name
) EntityActivities
WHERE ActivityName = 'Email'
AND EntityOwnsActivity = 0
ORDER BY
EntityName
C#.NET API
using (OrganizationServiceProxy _serviceProxy =
new OrganizationServiceProxy(
new Uri(".../XRMServices/2011/Organization.svc"), null, null, null))
{
_serviceProxy.EnableProxyTypes();
RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest()
{
EntityFilters = EntityFilters.Entity,
RetrieveAsIfPublished = true
};
// Retrieve the MetaData.
EntityMetadata[] entities =
((RetrieveAllEntitiesResponse)_serviceProxy.Execute(request)).EntityMetadata;
var ents = from e1 in entities.Where(x => x.IsActivity != true)
.Where(x => x.IsIntersect != true)
from e2 in entities.Where(x => x.IsActivity == true)
select new
{
entityName = e1.SchemaName
,
activityName = e2.SchemaName
};
//at this point, because of the limited nature of the Linq provider for left joins
//and sums, probably the best approach is to do a fetch query on each entity/activity
//combo, do some sort of sum and find out which combos have matches
// in the activity pointer table
//API = very inefficient; maybe improved in next CRM release? Let's hope so!
}