Query showing wrong result - sql

My below query gets records from table penilaian_header & penilaian_detail
select *
from
(
select
row, a.tanggal,b.OutletCode,c.Nilai,a.Nip,b.Fullname,a.KodePenilaian,
f.Description as posisilama, d.ShortDesc as posisibaru
from penilaian_header a
left join Employee b on a.Nip = b.Nip
left join Position f on b.PositionCode = f.PositionCode
left join Position d on a.PositionCode = d.PositionCode
left join Penilaian_Detail e on a.KodePenilaian = e.KodePenilaianH
left join arealeader g on g.OutletCode = b.OutletCode
left join (
select
ROW_NUMBER() OVER(PARTITION BY KodePenilaianH ORDER BY idPenilaiand DESC) AS Row,
Nilai,
KodePenilaianH
from penilaian_Detail
) c on a.KodePenilaian = e.KodePenilaianH
where a.Outlet like '%%' and Periode like '%%'
) nilai
pivot
(
sum(nilai) for row in ([1],[2],[3],[4],[5])
) piv;
My record in penilaian_header
My record in penilaian_detail
When I run my query, I get this result.
The result should be same as penilaian_detail. Please tell me how to fix it.
http://sqlfiddle.com/#!3/f7e4d/8
Thanks to #dhruvjoshi for explanation. Now the results are like what i'm expected
first, I delete this
left join Penilaian_Detail e on a.KodePenilaian = e.KodePenilaianH
then i change this
on a.KodePenilaian = e.KodePenilaianH to on a.KodePenilaian = c.KodePenilaianH

The problem was that because of JOINs you had repeated rows in result set for inner query.
See inner query fiddle evaluation
Corrected query is below
select *
from
(
select
distinct ---added distinct here to avoid repetition
row, a.tanggal,b.OutletCode,c.Nilai,a.Nip,b.Fullname,a.KodePenilaian,f.Description as posisilama,d.ShortDesc as posisibaru
from penilaian_header a
left join Employee b on a.Nip = b.Nip
left join Position f on b.PositionCode = f.PositionCode
left join Position d on a.PositionCode = d.PositionCode
left join Penilaian_Detail e on a.KodePenilaian = e.KodePenilaianH
left join arealeader g on g.OutletCode = b.OutletCode
left join (
select
ROW_NUMBER() OVER(PARTITION BY KodePenilaianH ORDER BY idPenilaiand DESC) AS Row,
Nilai,KodePenilaianH
from penilaian_Detail
) c on a.KodePenilaian = e.KodePenilaianH
) nilai
pivot
(
sum(nilai)
for row in ([1],[2],[3],[4],[5])
) piv;
SQL demo link

Related

Finding the count

I have the following SQL query and need to know the count of companyid as I can see repeating data. How do I find the count of it. Following is the query
SELECT a.companyId 'companyId'
, i.orgDebtType 'orgDebtType'
, d.ratingTypeName 'ratingTypeName'
, c.currentRatingSymbol 'currentRatingSymbol'
, c.ratingStatusIndicator 'ratingStatusIndicator'
, g.qualifierValue 'qualifierValue'
, c.ratingdate 'ratingDate'
, h.value 'outlook'
FROM ciqRatingEntity a
JOIN ciqcompany com
on com.companyId = a.companyId
JOIN ciqratingobjectdetail b ON a.entitySymbolValue = b.objectSymbolValue
JOIN ciqRatingData c ON b.ratingObjectKey = c.ratingObjectKey
JOIN ciqRatingType d ON b.ratingTypeId = d.ratingTypeId
JOIN ciqRatingOrgDebtType i ON i.orgDebtTypeId=b.orgDebtTypeId
JOIN ciqRatingEntityData red ON red.entitySymbolValue=a.entitySymbolValue
AND red.ratingDataItemId='1' ---CoName
LEFT JOIN ciqRatingDataToQualifier f ON f.ratingDataId = c.ratingDataId
LEFT JOIN ciqRatingQualifiervalueType g ON g.qualifiervalueid = f.qualifierValueId
LEFT JOIN ciqRatingValueType h ON h.ratingValueId = c.outlookValueId
WHERE 1=1
AND b.ratingTypeId IN ( '130', '131', '126', '254' )
-- and a.companyId = #companyId
AND a.companyId IN
(SELECT distinct TOP 2000000
c.companyId
FROM ciqCompany c
inner join ciqCompanyStatusType cst on cst.companystatustypeid = c.companystatustypeid
inner join ciqCompanyType ct on ct.companyTypeId = c.companyTypeId
inner join refReportingTemplateType rep on rep.templateTypeId = c.reportingtemplateTypeId
inner join refCountryGeo rcg on c.countryId = rcg.countryId
inner join refState rs on rs.stateId = c.stateId
inner join ciqSimpleIndustry sc on sc.simpleIndustryId = c.simpleIndustryId
ORDER BY companyid desc)
ORDER BY companyId DESC, c.ratingdate, b.ratingTypeId, c.ratingStatusIndicator
This will list where there are duplicate companyID's
SELECT companyId, count(*) as Recs
FROM ciqCompany
GROUP BY ciqCompany
HAVING count(*) > 1
I understand that you wish to add a column to the query with the count of each companyId, you can use COUNT() OVER():
select count(a.companyId) over (partition by a.companyId) as companyCount,
<rest of the columns>
from ciqRatingEntity a
join <rest of the query>
This would return in each row the count of the companyId of that row without grouping the results.

Max Query Over Partition

I want to select max values related to query, but all results are coming. Any idea ?
QUERY
SELECT MAXRecID,MAXSetID,MAXRID,PreReifiedValue,ComplianceState
FROM v_CI_CurrentComplianceStatus as A
INNER JOIN v_CIRules as B
ON B.CI_ID = A.CI_ID
INNER JOIN v_R_System as C
ON C.ResourceID = A.ItemKey
INNER JOIN
( SELECT PreReifiedValue,setting_CI_ID,
MAX(RecordID) AS MAXRecID,
MAX(SettingID) AS MAXSetID,
MAX(RuleID) AS MAXRID
FROM CI_CurrentRuleDetail
GROUP BY PreReifiedValue,Setting_CI_ID,instancedata
) AS D
ON D.Setting_CI_ID = A.CI_ID
GROUP by MAXRecID,MAXSetID,MAXRID,PreReifiedValue,rulename,ComplianceState
Results
MAXRecID MAXSetID MAXRID PreReifiedValue ComplianceState
72057594038117564 16780566 16780622 10 2
72057594038117565 16780570 16780620 0 2
Try this query
SELECT
MAX(tmp.MAXRecID), MAX(tmp.MAXSetID), MAX(tmp.MAXRID), MAX(tmp.PreReifiedValue), MAX(tmp.ComplianceState)
FROM (
SELECT MAXRecID,MAXSetID,MAXRID,PreReifiedValue,ComplianceState
FROM v_CI_CurrentComplianceStatus as A
INNER JOIN v_CIRules as B
ON B.CI_ID = A.CI_ID
INNER JOIN v_R_System as C
ON C.ResourceID = A.ItemKey
INNER JOIN
( SELECT PreReifiedValue,setting_CI_ID,
MAX(RecordID) AS MAXRecID,
MAX(SettingID) AS MAXSetID,
MAX(RuleID) AS MAXRID
FROM CI_CurrentRuleDetail
GROUP BY PreReifiedValue,Setting_CI_ID,instancedata
) AS D
ON D.Setting_CI_ID = A.CI_ID
) AS tmp
GROUP by tmp.MAXRecID, tmp.MAXSetID, tmp.MAXRID, tmp.PreReifiedValue, tmp.rulename, tmp.ComplianceState

Error when adding order by

Goodday, Please check my query first.
SELECT *
FROM
(
SELECT DISTINCT row, a.tanggal, b.OutletCode, c.Nilai, a.Nip, b.Fullname,
a.KodePenilaian, f.Description AS posisilama, d.ShortDesc AS posisibaru
FROM penilaian_header a
LEFT JOIN Employee b
ON a.Nip = b.Nip
LEFT JOIN Position f
ON b.PositionCode = f.PositionCode
LEFT JOIN Position d
ON a.PositionCode = d.PositionCode
LEFT JOIN arealeader g
ON g.OutletCode = b.OutletCode
LEFT JOIN
(
SELECT ROW_NUMBER() OVER (PARTITION BY KodePenilaianH
ORDER BY idPenilaiand DESC) AS Row,
Nilai, KodePenilaianH
FROM penilaian_Detail
) c
ON a.KodePenilaian = c.KodePenilaianH
WHERE a.Outlet LIKE '%%' AND Periode LIKE '%%'
ORDER BY b.OutletCode ASC
) nilai PIVOT (SUM(nilai) FOR ROW IN ([1],[2],[3],[4],[5])) piv;
My problem is when i'm add Order by my query error. Here is the error :
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
Without Order By my query working fine.
I believe that ORDER BY b.OutletCode ASC is the cause of the error, rather than the ORDER BY inside the partition, which is necessary and should be allowed.
If you want to return all records, you can use TOP with a large number, e.g.
SELECT *
FROM
(
SELECT DISTINCT TOP 2147483647 row, a.tanggal, b.OutletCode, c.Nilai, a.Nip,
b.Fullname, a.KodePenilaian, f.Description AS posisilama, d.ShortDesc AS posisibaru
FROM penilaian_header a
LEFT JOIN Employee b
ON a.Nip = b.Nip
...
ORDER BY b.OutletCode ASC
) nilai PIVOT (SUM(nilai) FOR ROW IN ([1],[2],[3],[4],[5])) piv;

Limiting result sets by future date - SQL

The Query below produces a record for each Entry in the SP_ScheduleEvent Table.
SELECT m.MaterialId, m.MaterialTitle, se.EventDateTime, c.ChannelName
FROM GB_Material m
LEFT OUTER JOIN SP_ScheduleEvent se on se.MaterialName = m.MaterialName
INNER JOIN SP_Schedule s on s.ScheduleID = se.ScheduleID
INNER JOIN GB_Channel c on c.ChannelID = s.ChannelID
WHERE LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%'
I want to limit the result set by the nearest future EventDateTime.
So per material name i would like to see one EventDateTime, which should be the nearest future date to the current time.
And lastly, a record may not exist in the SP_ScheduleEvent table for a particular materialname, in which case there should be null returned for the EventDateTime column
SQLFiddle
How would i go about doing this?
First, your LEFT JOIN is immaterial, because the subsequent joins make it an INNER JOIN. Either use LEFT JOIN throughout the FROM statement or switch to INNER JOIN.
I think you can use ROW_NUMBER():
SELECT t.*
FROM (SELECT m.MaterialId, m.MaterialName, m.MaterialTitle, se.EventDateTime,
ROW_NUMBER() over (PARTITION BY m.MaterialId OVER se.EventDateTime DESC) as seqnum
FROM GB_Material m INNER JOIN
SP_ScheduleEvent se
on se.MaterialName = m.MaterialName INNER JOIN
SP_Schedule s
on s.ScheduleID = se.ScheduleID INNER JOIN
GB_Channel c
on c.ChannelID = s.ChannelID
WHERE se.EventDateTime > getdate() AND
(LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%')
) t
WHERE seqnum = 1
ORDER BY se.EventDateTime;
Use the ROW_NUMBER() function:
WITH cte AS (
SELECT m.MaterialId, m.MaterialTitle, se.EventDateTime, c.ChannelName,
ROW_NUMBER() OVER (PARTITION BY m.MaterialId ORDER BY EventDateTime ASC) AS rn
FROM GB_Material m
LEFT OUTER JOIN SP_ScheduleEvent se on se.MaterialName = m.MaterialName
LEFT OUTER JOIN SP_Schedule s on s.ScheduleID = se.ScheduleID
LEFT OUTER JOIN GB_Channel c on c.ChannelID = s.ChannelID
WHERE LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%'
AND se.EventDateTime > GETDATE()
)
SELECT * FROM cte
WHERE rn=1

how to join a table on a subquery that uses order by and limit

For each row from table tClass matching a given where clause,
join on the first row in tEv, sorted by time, where tEv.class_id = tClass.class_id
The following code throws the error
ORA-01799: a column may not be outer-joined to a subquery
select
c.class_id,
c.class_name,
e.start_time,
e.ev_id
from
tClass c
left join tEv e on (
e.ev_id = (
select
ss1.ev_id
from (
select
ed.ev_id
from
tEvDisp ed,
tEv e
where
ed.class_id = c.class_id
and ed.viewable = 'Y'
and ed.display_until > localtimestamp
and e.ev_id = ed.ev_id
order by
e.start_time
) ss1
where
rownum = 1
)
)
where
c.is_matching = 'Y';
How can this be rewritten to do what is described?
The above is for oracle, but needs to work in sqlite (substituting where necessary)
No idea about SQLite - that would need to be a separate question if this doesn't work - but for Oracle you could do something like this:
select c.class_id,
c.class_name,
e.start_time,
e.ev_id
from tClass c
left join (
select class_id, ev_id, start_time
from (
select ed.class_id,
ed.ev_id,
e.start_time,
row_number() over (partition by ed.class_id order by e.start_time) as rn
from tEvDisp ed
join tEv e on e.ev_id = ed.ev_id
where ed.viewable = 'Y'
and ed.display_until > localtimestamp
)
where rn = 1
) e on e.class_id = c.class_id
where c.is_matching = 'Y';
This uses a subquery which finds the most tEv data, using an analytic row_number() to identify the latest data for each class_id, which is restricted by the rn = 1 filter.
That subquery, consisting of at most one row per class_id, is then used the left outer join against tClass.
This sort of construct should get you what you need. You can fix the details.
select c.classid
, c.classname
, temp.maxstarttime
from tClass c left join (
select c.classid id
max(e.start_time) maxstarttime
from tClass join tEv on tEv.classId = tClass.ClassId
where whatever
group by c.classid) temp on c.classid = temp.id