I have three columns
ThreadID
DateTime
CommentID
ReplyCommentID
Query
WITH CTE AS ( SELECT CommentID ,
CommentUserName,
ReplyCommentID ,
CommentID AS ThreadID ,
CAST( CommentID AS VARCHAR( MAX ) ) AS PathStr,
HtmlComment ,
CommentPostDocumentID ,
CommentIsApproved,
CommentDate
FROM Blog_CommentDetails AS T WITH(NOLOCK)
WHERE ReplyCommentID IS NULL
UNION ALL
SELECT T.CommentID ,
T.CommentUserName,
T.ReplyCommentID ,
CTE.ThreadID ,
PathStr + '-'+ CAST( T.ReplyCommentID AS VARCHAR( MAX ) ) AS PathStr,
T.HtmlComment ,
t.CommentPostDocumentID ,
t.CommentIsApproved,
T.CommentDate
FROM Blog_CommentDetails AS T WITH(NOLOCK)
JOIN CTE
ON T.ReplyCommentID = CTE.CommentID
WHERE T.ReplyCommentID IS NOT NULL)
SELECT *
FROM CTE
WHERE CommentPostDocumentID = 15 AND CommentIsApproved=1
ORDER BY ThreadID, PathStr ,
CommentDate DESC;
I need to order by ThreadID ascending first
Then i need to order by CommentID ascending second
Then i need to order by date descending third
But one condision, when there is commenid and replycommendid matches for two rows, rows with commenid should be first.
How can i write an order by for this?
ORDER BY ThreadID,CommentID,DateTime desc,
IF(ReplyCommentID == CommentID)
then
rows with commentid should be first
Current result:
But the expected result is:
You can use a calculated value for ordering; However, as calculation requires attributes from separate rows, these rows have first to be combined.
Without demo data in textual form, which I could take over to my environment, it's a bit hard to test.
The following schema is very close to your requirements, if we consider a as representing CommentId and b standing for ReplyCommentID:
create table test (
a int,
b int
);
insert into test (a,b) values (1,null), (2,1), (3,2), (4,1);
select distinct test.a as a, test.b as b, case when (test.b=test2.a or test.b is null) then 0 else 1 end as priority
from test left join test test2 on test.b = test2.a and test2.b is null
order by priority,a,b
Note that the order compared to an order by a,b changes analogously to what you expect in your sample data.
Givent that, when applying to your query (after the WITH CTE...-part), it should look as follows. As mentioned above, I cannot test it, so please do not throw stones on me if it does not work immediately:
SELECT distinct cte.*, case when (cte.ReplyCommentID =cte2.CommentId or cte.ReplyCommentID is null) then 0 else 1 end as priority
FROM CTE left join CTE cte2 on cte.ReplyCommentID = cte2.CommentId and cte2.ReplyCommentID is null
WHERE CommentPostDocumentID = 15 AND CommentIsApproved=1
ORDER BY ThreadID, priority, CommentId, PathStr , CommentDate DESC;
The following extensive example will walk through a tree of comments based on CommentID and ReplyCommentID (which serves as the ParentID). Children of the same ReplyCommentID are ordered by CommentDate DESC:
DECLARE #Table TABLE (
CommentID INT,
ReplyCommentID INT,
CommentDate DATETIME
);
INSERT INTO #Table VALUES
(140,NULL, CAST('20170109' AS DATETIME))
,(141,NULL, CAST('20170110' AS DATETIME))
,(142,141, CAST('20170111' AS DATETIME))
,(143,141, CAST('20170112' AS DATETIME))
,(144,141, CAST('20170113' AS DATETIME))
,(145,144, CAST('20170114' AS DATETIME))
,(146,NULL, CAST('20170115' AS DATETIME));
WITH [Statistics] AS (
SELECT Records.CommentID, Records.ReplyCommentID
, COUNT(Children.CommentID) AS NrOfChildren
, ROW_NUMBER() OVER (PARTITION BY Records.ReplyCommentID ORDER BY Records.CommentDate DESC) AS NthChild
, COUNT(Records.CommentID) OVER (PARTITION BY Records.ReplyCommentID) AS NrOfSiblings
FROM #Table Records
LEFT JOIN #Table Children ON Records.CommentID = Children.ReplyCommentID
GROUP BY Records.CommentID, Records.ReplyCommentID, Records.CommentDate
)
, Tree AS (
SELECT *
, 1 AS [Order]
, 0 AS [Rerouting]
, CAST(-1 AS INT) AS ReroutedFromNthChild
FROM [Statistics] AS TreeNode
WHERE ReplyCommentID IS NULL AND NthChild = 1
UNION ALL
SELECT NextNode.*
, TreeNode.[Order] + 1 AS [Order]
, CASE
WHEN (TreeNode.NrOfChildren = 0 AND TreeNode.NthChild = TreeNode.NrOfSiblings AND TreeNode.ReplyCommentID = NextNode.CommentID)
OR (TreeNode.Rerouting = 1 AND TreeNode.ReroutedFromNthChild = TreeNode.NrOfChildren AND TreeNode.ReplyCommentID = NextNode.CommentID)
THEN 1
ELSE 0
END AS [Rerouting]
, CAST(TreeNode.NthChild AS INT) AS ReroutedFromNthChild
FROM Tree AS TreeNode
JOIN [Statistics] AS NextNode
--Has children, so select first child
ON (TreeNode.Rerouting = 0 AND TreeNode.NrOfChildren > 0 AND NextNode.NthChild = 1 AND TreeNode.CommentID = NextNode.ReplyCommentID)
--Has no children, so select next sibling
OR (TreeNode.Rerouting = 0 AND TreeNode.NrOfChildren = 0 AND TreeNode.NthChild + 1 = NextNode.NthChild AND (TreeNode.ReplyCommentID = NextNode.ReplyCommentID OR (TreeNode.ReplyCommentID IS NULL AND NextNode.ReplyCommentID IS NULL)))
--Has no children or following siblings, so retrace the step (reroute)
OR (TreeNode.Rerouting = 0 AND TreeNode.NrOfChildren = 0 AND TreeNode.NthChild = TreeNode.NrOfSiblings AND TreeNode.ReplyCommentID = NextNode.CommentID)
--Was rerouting but has children, so back on track and follow the next child
OR (TreeNode.Rerouting = 1 AND TreeNode.ReroutedFromNthChild < TreeNode.NrOfChildren AND TreeNode.ReroutedFromNthChild + 1 = NextNode.NthChild AND TreeNode.CommentID = NextNode.ReplyCommentID)
--Was rerouting and has no other children, so continue rerouting
OR (TreeNode.Rerouting = 1 AND TreeNode.ReroutedFromNthChild = TreeNode.NrOfChildren AND TreeNode.ReplyCommentID = NextNode.CommentID)
--Rerouted to the top without children left, jumping to the next sibling
OR (TreeNode.Rerouting = 1 AND (TreeNode.ReroutedFromNthChild = TreeNode.NrOfChildren OR TreeNode.NrOfChildren = 0) AND TreeNode.NthChild + 1 = NextNode.NthChild AND TreeNode.ReplyCommentID IS NULL AND NextNode.ReplyCommentID IS NULL)
)
select *
from Tree
where Rerouting = 0
ORDER BY [Order]
Related
I have lets say two terms term A (previous)and term B (current) , i need to check if pol_cancl_date is null or not in term A , there is a transaction_sequence_number , i need to see if the pol_cncl_date is existing in the greatest A.transaction_sequence_number and if greatest( A.transaction_sequence_number ) is the greated when compared to all B.transaction_sequence_number numbers , if it is then i would want to check for pol_cancl_dates's existence and apply a logic
WITH x AS (
SELECT * FROM (
SELECT
pol_num
,term_start_dt
,term_end_dt,pol_cancel_dt
,trans_seq_num
,future_cancel_dt
,DENSE_RANK() OVER (PARTITION BY pol_num ORDER BY term_end_dt DESC) AS flag
FROM `gcp-ent-datalake-preprod.trns_prop_pol_hs_horison.prop_cost`
--WHERE pol_num IN ('30766675','33896642')
-- pol_num = '33288489'
ORDER BY term_start_dt, term_end_dt DESC
)
)
SELECT
*
,CASE
WHEN prior_pol_cancel_dt IS NOT NULL AND current_trans_seq_num < prior_trans_seq_num THEN prior_pol_cancel_dt
ELSE current_pol_cancel_dt
END apply_cancelled_renewal_dt
FROM (
SELECT
MAX(a.pol_num) AS current_pol_num
,MAX(a.term_start_dt) AS current_term_start_dt
,a.term_end_dt AS current_term_ent_dt
,MAX(a.pol_cancel_dt) AS current_pol_cancel_dt
,MAX(a.trans_seq_num) AS current_trans_seq_num
,MAX(a.future_cancel_dt) AS current_future_cancel_dt
,MAX(a.flag) AS current_flag
,MAX(b.pol_num) AS prior_pol_num
,MAX(b.term_start_dt) AS prior_term_start_dt
,b.term_end_dt AS prior_term_end_dt
,MAX(b.pol_cancel_dt) AS prior_pol_cancel_dt
,MAX(b.trans_seq_num) AS prior_trans_seq_num
,MAX(b.future_cancel_dt) AS prior_future_cancel_dt
,MAX(b.flag) AS prior_flag
FROM (
SELECT * FROM x WHERE flag=1) a
INNER JOIN(
SELECT * FROM x WHERE flag = 2 ) b
ON a.pol_num = b.pol_num AND a.flag = b.flag - 1
WHERE a.pol_cancel_dt IS NOT NULL
AND b.pol_cancel_dt IS NOT NULL
AND greatest(a.trans_seq_num) < b.trans_seq_num
-- AND a.trans_seq_num = GREATEST(a.trans_seq_num)
-- AND b.trans_seq_num = GREATEST(b.trans_seq_num)
GROUP BY a.term_end_dt, b.term_end_dt
)
--WHERE a.term_start_dt < b.term_start_dt
--if prior term GREATEST (trans_sewq num
this logic is still not giving me some results , one thing is that trans_seq_num doesn't necessarily have to be one less
I have a table called recipes with following data.
page_no title
-----------------
1 pancake
2 pizza
3 pasta
5 cookie
page_no 0 is always blank, and missing page_no are blank, I want output as below, for the blank page NULL values in the result.
left_title right_title
------------------------
NULL pancake
Pizza pasta
NULL cookie
I have tried this SQL statement, but it's not returning the desired output:
SELECT
CASE WHEN id % 2 = 0
THEN title
END AS left_title,
CASE WHEN id %2 != 0
THEN title
END AS right_title
FROM
recipes
You are quite close. You just need aggregation:
select max(case when id % 2 = 0 then title end) as left_title,
max(case when id % 2 = 1 then title end) as right_title
from recipes
group by id / 2
order by min(id);
SQL Server does integer division, so id / 2 is always an integer.
Using CTE.. this should be give you a good CTE overview
DECLARE #table TABLE (
pageno int,
title varchar(30)
)
INSERT INTO #table
VALUES (1, 'pancake')
, (2, 'pizza')
, (3, 'pasta')
, (5, 'cookie')
;
WITH cte_pages
AS ( -- generate page numbers
SELECT
0 n,
MAX(pageno) maxpgno
FROM #table
UNION ALL
SELECT
n + 1 n,
maxpgno
FROM cte_pages
WHERE n <= maxpgno),
cte_left
AS ( --- even
SELECT
n,
ROW_NUMBER() OVER (ORDER BY n) rn
FROM cte_pages
WHERE n % 2 = 0),
cte_right
AS ( --- odd
SELECT
n,
ROW_NUMBER() OVER (ORDER BY n) rn
FROM cte_pages
WHERE n % 2 <> 0)
SELECT
tl.title left_title,
tr.title right_title --- final output
FROM cte_left l
INNER JOIN cte_right r
ON l.rn = r.rn
LEFT OUTER JOIN #table tl
ON tl.pageno = l.n
LEFT OUTER JOIN #table tr
ON tr.pageno = r.n
The select part is fine, I can run it and get result, but if I insert the query result into a table, the "not a group by expression" exception was thrown, see my sql statement below:
INSERT INTO RAWDATA_FACT
(
LINEITEMID
,CALENDARYEAR
,CALENDARQUARTER
,CALENDARMONTH
,DEPARTMENTID
,PRODUCTID
,DEALERID
,ACTUALVALUE
,TARGETVALUE
,AGGREGATION
,TODATE
,CREATEDATE
,BATCH_ID
)
select parentid
,calendaryear
,calendarquarter
,calendarmonth
,departmentid
,productid
,dealerid
,sum(case when unaryoperator = '-' then actualvalue * (-1)
when unaryoperator = '~' then actualvalue * 0
else actualvalue
end
) actualvalue
,sum(case when unaryoperator = '-' then targetvalue * (-1)
when unaryoperator = '~' then targetvalue * 0
else targetvalue
end
) targetvalue
,aggregation
,todate
,sysdate createdate
,'201808' batch_id--v_batch_ID
from
(
select
x.parentid
, x.unaryoperator
, y.calendaryear
, y.calendarquarter
, y.calendarmonth
, y.departmentid
, y.productid
, y.dealerid
, y.actualvalue
, y.targetvalue
, y.aggregation
, y.todate
from
(select substr(lineitemid,instr(lineitemid,'_')+1) lineitemid,
parentid, unaryoperator from lineitem_temp where levelid = 14 /*v_cur_level*/) x
inner join
(select lineitemid,calendaryear, calendarquarter, calendarmonth, departmentid, productid, dealerid,
coalesce(actualvalue,0) actualvalue,coalesce(targetvalue,0) targetvalue,
aggregation, todate
from RAWDATA_FACT where BATCH_ID = '201808'/*v_batch_ID*/) y --eg. 201809
on x.lineitemid = y.lineitemid
--parent node's id contains "_" will not take part in calculation from current level to parent level
where regexp_like(x.parentid , '^\d+$') and not exists
--parent node contains formula will not participate calculation from current level to parent level
(select 1 from LINEITEM_TEMP where lineitemid = x.parentid and custommember is not null)
) t
GROUP BY
t.parentid
, t.calendaryear
, t.calendarquarter
, t.calendarmonth
, t.departmentid
, t.productid
, t.dealerid
, t.aggregation
, t.todate
;
who can tell me why? is there a way to insert the result into that table? If I run the select parts, it works fine, but if I want to insert the result into that table, it reports that exception.
Just a question on displaying a row on flight level and displaying a count on how many crew members on that flight.
I want to change the output so it will only display a single record at flight level and it will display two additional columns. One column (cabincrew) is the count of crew members that have the 'CREWTYPE' = 'F' and the other column (cockpitcrew) is the count of crew members that have the `'CREWTYPE' = 'C'.
So the query result should look like:
Flight DepartureDate DepartureAirport CREWBASE CockpitCrew CabinCrew
LS361 2016-05-19 BFS BFS 0 3
Can I have a little help tweaking the below query please:
WITH CTE AS (
SELECT cd.*, c.*, l.Carrier, l.FlightNumber, l.Suffix, l.ScheduledDepartureDate, l.ScheduledDepartureAirport
FROM
(SELECT *, ROW_NUMBER() OVER(PARTITION BY LegKey ORDER BY UpdateID DESC) AS RowNumber FROM Data.Crew) c
INNER JOIN
Data.CrewDetail cd
ON c.UpdateID = cd.CrewUpdateID
AND cd.IsPassive = 0
AND RowNumber = 1
INNER JOIN
Data.Leg l
ON c.LegKey = l.LegKey
)
SELECT
sac.Airline + CAST(sac.FlightNumber AS VARCHAR) + sac.Suffix AS Flight
, sac.DepartureDate
, sac.DepartureAirport
, sac.CREWBASE
, sac.CREWTYPE
, sac.EMPNO
, sac.FIRSTNAME
, sac.LASTNAME
, sac.SEX
FROM
Staging.SabreAssignedCrew sac
LEFT JOIN CTE cte
ON sac.Airline + CAST(sac.FlightNumber AS VARCHAR) + sac.Suffix = cte.Carrier + CAST(cte.FlightNumber AS VARCHAR) + cte.Suffix
AND sac.DepartureDate = cte.ScheduledDepartureDate
PLEASE TRY THIS.
SELECT Flight,
DepartureDate,
DepartureAirport,
CREWBASE,
SUM(CASE WHEN CREWTYPE = 'F' THEN 1 ELSE 0 END) AS CabinCrew ,
SUM(CASE WHEN CREWTYPE = 'C' THEN 1 ELSE 0 END) AS CockpitCrew
FROM #Table
GROUP BY Flight, DepartureDate, DepartureAirport, CREWBASE
Please Try This:
select Flight, DepartureDate, DepartureAirport,CREWBASE,
count(case when CREWTYPE='F' then 1 end ) as CabinCrew,count(case when CREWTYPE='C' then 1 end ) as CockpitCrew
from Staging.SabreAssignedCrew
group by Flight, DepartureDate, DepartureAirport,CREWBASE
I have following table:
Card(
MembershipNumber,
EmbossLine,
status,
EmbossName
)
with sample data
(0009,0321,'E0','Finn')
(0009,0322,'E1','Finn')
(0004,0356,'E0','Mary')
(0004,0398,'E0','Mary')
(0004,0382,'E1','Mary')
I want to retrieve rows such that only those rows should appear that have count of MembershipNumber > 1 AND count of status='E0' > 1.
For Example The query should return following result
(0004,0356,'E0','Mary')
(0004,0398,'E0','Mary')
I have the query for filtering it with MembershipNumber count but cant figure out how to filter by status='E0'. Here's the query so far
SELECT *
FROM (SELECT *,
Count(MembershipNumber)OVER(partition BY EmbossName) AS cnt
FROM card) A
WHERE cnt > 1
You can just add WHERE status = 'E0' inside your subquery:
SQL Fiddle (credit to Raging Bull for the fiddle)
SELECT *
FROM (
SELECT *,
COUNT(MembershipNumber) OVER(PARTITION BY EmbossName) AS cnt
FROM card
WHERE status = 'E0'
)A
WHERE cnt > 1
You can do it this way:
select t1.*
from card t1 left join
(select EmbossName
from card
where [status]='E0'
group by EmbossName,[status]
having count(MembershipNumber)>1 ) t2 on t1.EmbossName=t2.EmbossName
where t2.EmbossName is not null and [status]='E0'
Result:
MembershipNumber EmbossLine status EmbossName
---------------------------------------------------
4 356 E0 Mary
4 398 E0 Mary
Sample result in SQL Fiddle
try :
WITH cnt AS (
SELECT MembershipNumber, status
FROM Card
WHERE status = 'E0'
GROUP BY MembershipNumber, status
HAVING COUNT(MembershipNumber) > 1 AND COUNT(status) > 1
)
SELECT c.*
FROM Card c
INNER JOIN cnt
ON c.MembershipNumber = cnt.MembershipNumber
AND c.status = cnt.status;
You can try this:
DECLARE #DataSource TABLE
(
[MembershipNumber] SMALLINT
,[EmbossLine] SMALLINT
,[status] CHAR(2)
,[EmbossName] VARCHAR(8)
);
INSERT INTO #DataSource ([MembershipNumber], [EmbossLine], [status], [EmbossName])
VALUES (0009,0321,'E0','Finn')
,(0009,0322,'E1','Finn')
,(0004,0356,'E0','Mary')
,(0004,0398,'E0','Mary')
,(0004,0382,'E1','Mary');
SELECT [MembershipNumber]
,[EmbossLine]
,[status]
,[EmbossName]
FROM
(
SELECT *
,COUNT([MembershipNumber]) OVER (PARTITION BY [EmbossName]) AS cnt1
,SUM(IIF([status] = 'E0' , 1, 0)) OVER (PARTITION BY [EmbossName]) AS cnt2
FROM #DataSource
) DS
WHERE cnt1 > 1
AND cnt2 > 1
AND [status] = 'E0';
The idea is to add a second counter, but instead of COUNT function to use SUM function for counting only the rows that have [status] = 'E0'. Then, in the where clause we are filtering by the two counters and [status] = 'E0'.