Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I have a sql statement that repeat a record sevral time I don't know why!
This is my statement:
select floor((a.created-c.created)*24)
|| ' HOURS ' ||
mod(floor((a.created-c.created)*24*60),60)
|| ' MINUTES ' ,a.pkey as AssignedGroupResponseTime,a.pkey,d.newString as AssignedGroup
from
(
select g.created,g.issueid as groupid1, ji.pkey ,ci.newString
from changegroup g
join jiraissue ji on (ji.id = g.issueid)
join changeitem ci on (ci.groupid = g.id)
where (g.created, ji.pkey) in (
select min(g.created) ,ji.pkey
from changegroup g
join changeitem ci on (ci.groupid = g.id)
join jiraissue ji on (ji.id = g.issueid)
join project p on (p.id = ji.project)
join priority pr on (pr.id = ji.priority)
where ci.field = 'Group'
and ci.oldString like 'Triage'
and p.pname = 'Change Management'
and pr.pname='P3'
and ji.created between '01/03/2011' and '16/08/2011'
group by ji.pkey
)) a
left join (
select ji.created, ji.id as groupid2 ,ji.pkey ,ci.newString
from jiraissue ji
join changegroup g on (g.issueid = ji.id)
join changeitem ci on (ci.groupid = g.id)
join project p on (p.id = ji.project)
where p.pname = 'Change Management'
and ci.field = 'Group'
and ci.oldString like 'Triage'
and ji.created between '01/03/2011' and '16/08/2011'
) b ON ( a.pkey = b.pkey)
left join (
select g.created, g.issueid as groupid1 ,ji.pkey ,ci.newString
from changegroup g
join jiraissue ji on (ji.id = g.issueid)
join changeitem ci on (ci.groupid = g.id)
where (g.created, ji.pkey) in (
select min(g.created) ,ji.pkey
from changegroup g
join changeitem ci on (ci.groupid = g.id)
join jiraissue ji on (ji.id = g.issueid)
join project p on (p.id = ji.project)
join priority pr on (pr.id = ji.priority)
where ci.field='assignee'
and ci.newString is not NULL
and p.pname = 'Change Management'
and pr.pname='P3'
and ji.created between '01/03/2011' and '16/08/2011'
group by ji.pkey)) c
ON (c.pkey = a.pkey)
left join (
select g.created, g.issueid as groupid1 ,ji.pkey ,ci.newString
from changegroup g
join jiraissue ji on (ji.id = g.issueid)
join changeitem ci on (ci.groupid = g.id)
where (g.created, ji.pkey) in (
select min(g.created) ,ji.pkey
from changegroup g
join changeitem ci on (ci.groupid = g.id)
join jiraissue ji on (ji.id = g.issueid)
join project p on (p.id = ji.project)
join priority pr on (pr.id = ji.priority)
where ci.field='assigned group'
and ci.newString is not NULL
and p.pname = 'Change Management'
and pr.pname='P3'
and ji.created between '01/03/2011' and '16/08/2011'
group by ji.pkey)) d
ON (d.pkey = c.pkey);
This is because you have duplicate keys on view b or c.
You can run separately this views and see what is wrong(duplicate key values).
In that view you have joins. Almost one join is made with a weak condition. That means you have duplicate matches for one condition.
Related
I have two queries as bellow
SELECT i.IncidentId, rl.Description Category FROM incident i
JOIN IncidentLikelihood l ON i.IncidentId = l.IncidentId
JOIN IncidentSeverity s ON i.IncidentId = s.IncidentId
JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId
JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId
And
SELECT i.IncidentId, rl.Description Category FROM incident i
JOIN incidentreportlikelihood l ON i.IncidentId = l.IncidentId
JOIN IncidentReportSeverity s ON i.IncidentId = s.IncidentId
JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId
JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId
I need to prepare a query with WITH clause such that within the clause either of the two query runs and then this view can be joined with another table.
Can you guys please suggest how I can proceed ?
I have tried UNION but that doesn't work for me. I am looking for something using IFEXISTS or EXISTS where - some like bellow :
WITH IncidentCategory AS (
SELECT i.IncidentId, rl.Description Category FROM incident i
JOIN IncidentLikelihood l ON i.IncidentId = l.IncidentId
JOIN IncidentSeverity s ON i.IncidentId = s.IncidentId
JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId
JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId
WHERE EXISTS (SELECT NULL)
OR
(SELECT i.IncidentId, rl.Description Category FROM incident i
JOIN incidentreportlikelihood l ON i.IncidentId = l.IncidentId
JOIN IncidentReportSeverity s ON i.IncidentId = s.IncidentId
JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId
JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId)
)
A little more to get the idea : for each of the rows [incidentid] if the the first query returns any result - it should show otherwise the second query result should show
If I understand the requirements correctly you have to run first query and if it has no results the second one should be run.
In fact you can union the both queries. The amount of rows in the second one should depend on the first. If count(*) for the first returns >0 the second query rows are included. See the example
SELECT i.IncidentId, rl.Description Category FROM incident i
JOIN IncidentLikelihood l ON i.IncidentId = l.IncidentId
JOIN IncidentSeverity s ON i.IncidentId = s.IncidentId
JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId
JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId
UNION
SELECT i.IncidentId, rl.Description Category FROM incident i
JOIN incidentreportlikelihood l ON i.IncidentId = l.IncidentId
JOIN IncidentReportSeverity s ON i.IncidentId = s.IncidentId
JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId
JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId
join (select count(*) as count
FROM incident i
JOIN IncidentLikelihood l ON i.IncidentId = l.IncidentId
JOIN IncidentSeverity s ON i.IncidentId = s.IncidentId
JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId
JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId) q1_copy on q1_copy.count=0
select * from iiasa_inventory.inv_device d
join iiasa_inventory.inv_type ty on d.type_id = ty.id
join iiasa_inventory.inv_category c on ty.category_id = c.id
join iiasa_inventory.inv_device_2_barcode b on b.device_id = d.id
join iiasa_inventory.inv_barcodes bc on b.barcode_id = bc.id
join iiasa_inventory.inv_status s on d.status = s.id
join iiasa_inventory.inv_brand br on ty.brand_id = br.id
left join iiasa_inventory.inv_supplier su on su.id = d.supplier_id
left join iiasa_inventory.inv_supplier sup on sup.id = d.maintenance_with
left join (select distinct device_id from
iiasa_inventory.inv_device_2_persons_cc) dp
on dp.device_id = d.id
where dp.active = 1
I am trying to select my data but the where-clause says that "dp.active" is an INVALID Identifier. This is probably because the table dp is in the subquery. I have tried to give it an alias name and some other things I found while browsing stackoverflow, but I cant seem to find a solution. Any idea?
This is Oracle PL/SQL.
Put the check for active = 1 in the subquery as shown below.
select * from iiasa_inventory.inv_device d
join iiasa_inventory.inv_type ty on d.type_id = ty.id
join iiasa_inventory.inv_category c on ty.category_id = c.id
join iiasa_inventory.inv_device_2_barcode b on b.device_id = d.id
join iiasa_inventory.inv_barcodes bc on b.barcode_id = bc.id
join iiasa_inventory.inv_status s on d.status = s.id
join iiasa_inventory.inv_brand br on ty.brand_id = br.id
left join iiasa_inventory.inv_supplier su on su.id = d.supplier_id
left join iiasa_inventory.inv_supplier sup on sup.id = d.maintenance_with
left join (select distinct device_id from iiasa_inventory.inv_device_2_persons_cc where active = 1) dp on dp.device_id = d.id
That is because you are not selecting active column in dp.
select * from iiasa_inventory.inv_device d
join iiasa_inventory.inv_type ty on d.type_id = ty.id
join iiasa_inventory.inv_category c on ty.category_id = c.id
join iiasa_inventory.inv_device_2_barcode b on b.device_id = d.id
join iiasa_inventory.inv_barcodes bc on b.barcode_id = bc.id
join iiasa_inventory.inv_status s on d.status = s.id
join iiasa_inventory.inv_brand br on ty.brand_id = br.id
left join iiasa_inventory.inv_supplier su on su.id = d.supplier_id
left join iiasa_inventory.inv_supplier sup on sup.id = d.maintenance_with
left join (select distinct device_id,active from iiasa_inventory.inv_device_2_persons_cc) dp on dp.device_id = d.id
where dp.active = 1
OR you can just filter from the subquery itself. Like:
left join (select distinct device_id
from iiasa_inventory.inv_device_2_persons_cc
where active=1) dp on dp.device_id = d.id
I require some help with my very shaky sql skills.
Say I have the following select statement:
SELECT DISTINCT
p.ProjectId,
p.Title,
i.Name,
p.StartDate,
p.EndDate,
ped.ProjectEthicsDocumentId,
st.Description AS StatusText
FROM
dbo.Project p
inner join dbo.WorkflowHistory w ON p.ProjectId = w.ProjectId
left join dbo.ProjectInstitution pi ON pi.ProjectId = p.ProjectId
left join dbo.Institution i ON i.InstitutionId = pi.InstitutionId
left join dbo.ProjectEthicsDocument ped on p.ProjectId = ped.ProjectId
left join dbo.Status st ON p.StatusId = st.StatusId
This will return all the projects and other relevant details from the relevant tables. Now, say I have 2 institutions for 'Project A'. This statement will return 2 rows for 'Project A', one for each institution. How do I set it so that it only returns the first row of each project it finds? I want one instance of every project with say the first institution found.
The easiest way is probably with the row_number() function:
select *
from (SELECT DISTINCT p.ProjectId, p.Title, i.Name, p.StartDate,p.EndDate,
ped.ProjectEthicsDocumentId, st.Description AS StatusText,
row_number() over (partition by p.ProjectId order by i.InstitutionId) as seqnum
FROM dbo.Project p
inner join dbo.WorkflowHistory w ON p.ProjectId = w.ProjectId
left join dbo.ProjectInstitution pi ON pi.ProjectId = p.ProjectId
left join dbo.Institution i ON i.InstitutionId = pi.InstitutionId
left join dbo.ProjectEthicsDocument ped on p.ProjectId = ped.ProjectId
left join dbo.Status st ON p.StatusId = st.StatusId
) p
where seqnum = 1;
You can move selecting institution name to a subquery. This way you it doesn't affect how other tables are joined.
SELECT DISTINCT
p.ProjectId,
p.Title,
(SELECT TOP 1 i.Name FROM dbo.Institution i
INNER JOIN dbo.ProjectInstitution pi ON i.InstitutionId = pi.InstitutionId
WHERE pi.ProjectId = p.ProjectId) AS Name,
p.StartDate,
p.EndDate,
ped.ProjectEthicsDocumentId,
st.Description AS StatusText
FROM
dbo.Project p
inner join dbo.WorkflowHistory w ON p.ProjectId = w.ProjectId
left join dbo.ProjectEthicsDocument ped on p.ProjectId = ped.ProjectId
left join dbo.Status st ON p.StatusId = st.StatusId
you could use
;with cte as
(
<your select statement> `,`
Row_number() over(partition by <column that has 2 records> order by ProjectId) as rn
)
--then do this
select * from cte where rn=1
I have this query and I am trying to group by surveyname but im getting this error:
Msg 8120, Level 16, State 1, Line 1
Column 'pvt.Follow Up' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
This is the query:
SELECT
surveyname, [Follow Up] AS Follow_Up, [Ambiance] AS Ambiance,
[Consultation] AS Consultation, [Procedure/Service] AS Procedure_Service
FROM
(SELECT
s.name surveyname, q.question, subq.answer subquestion,aw.answerweight,
aw.score, rc.categoryname, sc.cweight
FROM survey.dbo.results r
JOIN survey.dbo.questions q ON r.questionidfk = q.id
LEFT JOIN survey.dbo.answers subq ON r.itemidfk = subq.id
LEFT JOIN survey.dbo.answers a ON r.answeridfk = a.id
JOIN survey.dbo.surveys s ON q.surveyidfk = s.id
join sigweb.dbo.survey_types_main stm on s.id = stm.surveyidfk
join survey.dbo.survey_results sr on r.owneridfk = sr.ownerid
join sigweb.dbo.BosleySurvey bs on bs.contactid = sr.contactid and stm.clientsurveytypeid = bs.surveytype
join sigweb.dbo.contact c on sr.contactid = c.contactid
join sigweb.dbo.patient p on p.contactid = c.contactid
join sigweb.dbo.doctor d on p.doctorid = d.doctorid
join sigweb.dbo.survey_tracking st on st.contactid = c.contactID and st.surveytypeid = stm.surveytypeid
left join survey.dbo.answerweighting aw on isnull(r.itemidfk, r.questionidfk) = aw.questionitemidfk and r.answeridfk = aw.answeridfk
left join survey.dbo.rating_categories rc on aw.categoryidfk = rc.id
left join survey.dbo.survey_categories sc on aw.categoryidfk = sc.categoryidfk and s.id = sc.surveyidfk
where
aw.answerWeight is not null) ps
PIVOT
(
AVG(score)
FOR categoryname IN
( [Follow Up], [Ambiance], [Consultation], [Procedure/Service])
) AS pvt
group by surveyname
This is an example of the results im getting
SURVEYNAME FOLLOW_UP Ambiance Consultation Procedure_Service
Review NULL NULL NULL 9.81
Review 9.54 NULL NULL NULL
Consultation 5 NULL NULL NULL
Consultation NULL 5 NULL NULL
Consultation NULL 5 NULL NULL
Consultation NULL 5 NULL NULL
Consultation NULL 5 NULL NULL
Consultation NULL 5 NULL NULL
Consultation NULL NULL 5 NULL
Consultation 5 NULL NULL NULL
Consultation NULL NULL 5 NULL
This is an example of the data before the pivot:
Review 6 Follow Up
Review 9 Procedure/Service
Consultation 5 Ambiance
Consultation 5 Ambiance
Consultation 5 Ambiance
Consultation 5 Ambiance
Consultation 5 Ambiance
Consultation 5 Ambiance
Consultation 5 Consultation
Consultation 5 Consultation
The idea is to group by the surveyname and have only two results in the end.
It appears that you are including too many columns in the inner SELECT, try to remove the columns:
q.question, subq.answer subquestion, aw.answerweight, sc.cweight
They are most likely making the rows DISTINCT so the GROUP BY does not work properly. So your query will be:
SELECT surveyname,
[Follow Up] AS Follow_Up,
[Ambiance] AS Ambiance,
[Consultation] AS Consultation,
[Procedure/Service] AS Procedure_Service
FROM
(
SELECT s.name surveyname,
aw.score,
rc.categoryname,
FROM survey.dbo.results r
JOIN survey.dbo.questions q
ON r.questionidfk = q.id
LEFT JOIN survey.dbo.answers subq
ON r.itemidfk = subq.id
LEFT JOIN survey.dbo.answers a
ON r.answeridfk = a.id
JOIN survey.dbo.surveys s
ON q.surveyidfk = s.id
join sigweb.dbo.survey_types_main stm
on s.id = stm.surveyidfk
join survey.dbo.survey_results sr
on r.owneridfk = sr.ownerid
join sigweb.dbo.BosleySurvey bs
on bs.contactid = sr.contactid
and stm.clientsurveytypeid = bs.surveytype
join sigweb.dbo.contact c
on sr.contactid = c.contactid
join sigweb.dbo.patient p
on p.contactid = c.contactid
join sigweb.dbo.doctor d on p.doctorid = d.doctorid
join sigweb.dbo.survey_tracking st
on st.contactid = c.contactID
and st.surveytypeid = stm.surveytypeid
left join survey.dbo.answerweighting aw
on isnull(r.itemidfk, r.questionidfk) = aw.questionitemidfk
and r.answeridfk = aw.answeridfk
left join survey.dbo.rating_categories rc
on aw.categoryidfk = rc.id
left join survey.dbo.survey_categories sc
on aw.categoryidfk = sc.categoryidfk and s.id = sc.surveyidfk
where aw.answerWeight is not null
) ps
PIVOT
(
AVG(score)
FOR categoryname IN
( [Follow Up], [Ambiance], [Consultation], [Procedure/Service])
) AS pvt
I am not sure where the error is coming from in what you have posted (I assume it is when you try and add GROUP BY SurveyName to the end of the query you have posted), but you need to remove the redundant columns from your subquery, so you only select the 3 columns you need, surveyname, score, and categoryname:
SELECT
surveyname, [Follow Up] AS Follow_Up, [Ambiance] AS Ambiance,
[Consultation] AS Consultation, [Procedure/Service] AS Procedure_Service
FROM
(SELECT
s.name surveyname, aw.score, rc.categoryname
FROM survey.dbo.results r
JOIN survey.dbo.questions q ON r.questionidfk = q.id
LEFT JOIN survey.dbo.answers subq ON r.itemidfk = subq.id
LEFT JOIN survey.dbo.answers a ON r.answeridfk = a.id
JOIN survey.dbo.surveys s ON q.surveyidfk = s.id
join sigweb.dbo.survey_types_main stm on s.id = stm.surveyidfk
join survey.dbo.survey_results sr on r.owneridfk = sr.ownerid
join sigweb.dbo.BosleySurvey bs on bs.contactid = sr.contactid and stm.clientsurveytypeid = bs.surveytype
join sigweb.dbo.contact c on sr.contactid = c.contactid
join sigweb.dbo.patient p on p.contactid = c.contactid
join sigweb.dbo.doctor d on p.doctorid = d.doctorid
join sigweb.dbo.survey_tracking st on st.contactid = c.contactID and st.surveytypeid = stm.surveytypeid
left join survey.dbo.answerweighting aw on isnull(r.itemidfk, r.questionidfk) = aw.questionitemidfk and r.answeridfk = aw.answeridfk
left join survey.dbo.rating_categories rc on aw.categoryidfk = rc.id
left join survey.dbo.survey_categories sc on aw.categoryidfk = sc.categoryidfk and s.id = sc.surveyidfk
where
aw.answerWeight is not null) ps
PIVOT
(
AVG(score)
FOR categoryname IN
( [Follow Up], [Ambiance], [Consultation], [Procedure/Service])
) AS pvt
In the background you are also grouping your end results by q.question, subq.answer subquestion,aw.answerweight, sc.cweight because they are included in the subquery, but because the are not in the select list you are not seeing immediately the effect this is having.
Here is original Query :, it generates o/p with two columns name (label, count) :
label count
Fails 1
Pass 3
and here is query I wrote which generates above data
select r.pname as resolution
,lb.label
,count(r.pname) as occurences
from issuelink
inner join jiraissue p on issuelink.source = p.id
inner join jiraissue c on issuelink.destination = c.id
inner join issuelinktype t on issuelink.linktype = t.id
inner join resolution r on c.resolution = r.id
inner join issuestatus istat on p.issuestatus = istat.sequence
inner join label lb on c.id = lb.issue
where t.linkname = 'jira_subtask_link'
and p.pkey in (#pkey)
and c.issuetype in ('13')
and r.pname not in ('Fails Smoke Test - General Failure', 'Fails Smoke Test - New Firmware Available')
and label in ('SmokeTest', 'fullcert', 'bfv', 'papercert')
group by r.pname;
As per your suggestion I tried using cross function, however its throwing an error of "please check syntax":
select 100.0 * fail.cnt / (fail.cnt + pass.cnt) as c
from (
select r.pname as label
, count(r.pname) as cnt
from issuelink
inner join jiraissue p on issuelink.source = p.id
inner join jiraissue c on issuelink.destination = c.id
inner join issuelinktype t on issuelink.linktype = t.id
inner join resolution r on c.resolution = r.id
inner join issuestatus istat on p.issuestatus = istat.sequence
inner join label lb on c.id = lb.issue
where t.linkname = 'jira_subtask_link'
and p.pkey in ('SRPDTVTPV-3')
and c.issuetype in ('13')
and r.pname not in ('Fails Smoke Test - General Failure', 'Fails Smoke Test - New Firmware Available')
and label in ('SmokeTest', 'fullcert', 'bfv', 'papercert')
group by r.pname
) as fail
cross join
(
select r.pname as label
, count(r.pname) as cnt
from issuelink
inner join jiraissue p on issuelink.source = p.id
inner join jiraissue c on issuelink.destination = c.id
inner join issuelinktype t on issuelink.linktype = t.id
inner join resolution r on c.resolution = r.id
inner join issuestatus istat on p.issuestatus = istat.sequence
inner join label lb on c.id = lb.issue
where t.linkname = 'jira_subtask_link'
and p.pkey in ('SRPDTVTPV-3')
and c.issuetype in ('13')
and r.pname not in ('Fails Smoke Test - General Failure', 'Fails Smoke Test - New Firmware Available')
and label in ('SmokeTest', 'fullcert', 'bfv', 'papercert')
group by r.pname
) as pass
where fail.label = 'Fails Certification'
and pass.label = 'Passes Certification'
Here's one way using a cross join:
select 100.0 * a.count / (a.count + b.count) as c
from YourQuery a
cross join
YourQuery b
where a.label = 'a'
and b.label = 'b'
Here's another approach using aggregates, a bit more tricky but only uses YourQuery once:
select 100.0 * cnt_a / (cnt_a + cnt_b) as c
from (
select max(case when label = 'a' then count end) as cnt_a
, max(case when label = 'b' then count end) as cnt_b
from YourQuery
) as SubQueryAlias