How to set a parameter value from a SQL Server CTE? - tsql

Given the following SQL:
;WITH Results AS
(
SELECT ItemListID, Title,
ROW_NUMBER() OVER(ORDER BY ItemListID DESC) as intRow,
COUNT(ItemListID) OVER() AS ActualNumberOfResults
FROM ItemData
WHERE FREETEXT(Title, #FTSSearchTerm)
AND WebsiteID = #WebsiteID
AND ContentTypeID = #ContentTypeID
AND GeoID2 = #GeoID
)
SELECT * FROM Results
WHERE intRow BETWEEN #intStartRow AND #intEndRow
ORDER BY ItemListID DESC
SELECT #NumberOfResultsReturned = ##ROWCOUNT
I would like to set a parameter, #ActualNumberOfResults to the value of TOP(1) ActualNumberOfResults that is returned from the CTE.
I used the following, after the CTE, but seems repetitive:
SELECT #ActualNumberOfResults = COUNT(*)
FROM ItemData
WHERE CONTAINS(Title, #FTSSearchTerm )
AND WebsiteID=#WebsiteID
How can I accomplish this?

;WITH cte AS
(
SELECT ItemListID, Title,
CASE WHEN ROW_NUMBER() OVER(ORDER BY ItemListID DESC)
BETWEEN #intStartRow AND #intEndRow THEN 1
END AS NumberOfResultsReturned,
COUNT(ItemListID) OVER() AS ActualNumberOfResults
FROM ItemData
WHERE FREETEXT(Title, #FTSSearchTerm)
AND WebsiteID = #WebsiteID
AND ContentTypeID = #ContentTypeID
AND GeoID2 = #GeoID
)
SELECT #NumberOfResultsReturned = COUNT(NumberOfResultsReturned),
#ActualNumberOfResults = MAX(ActualNumberOfResults)
FROM cte
Demo on SQLFiddle

Visit check this link on the MSDN> http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/c774bb71-84c9-44ce-bfce-a256ecbf56ab
;WITH CTE1
AS (...)
SELECT * FROM CTE1
;WITH CTE2
AS (...)
SELECT * FROM CTE2
here your code
;WITH Results AS
(
SELECT ItemListID, Title,
ROW_NUMBER() OVER(ORDER BY ItemListID DESC) as intRow,
COUNT(ItemListID) OVER() AS ActualNumberOfResults
FROM ItemData
WHERE FREETEXT(Title, #FTSSearchTerm)
AND WebsiteID = #WebsiteID
AND ContentTypeID = #ContentTypeID
AND GeoID2 = #GeoID
)
SELECT * FROM Results
WHERE intRow BETWEEN #intStartRow AND #intEndRow
ORDER BY ItemListID DESC
SELECT #NumberOfResultsReturned = ##ROWCOUNT
;WITH Results1 AS
(
SELECT ItemListID, Title,
ROW_NUMBER() OVER(ORDER BY ItemListID DESC) as intRow,
COUNT(ItemListID) OVER() AS ActualNumberOfResults
FROM ItemData
WHERE FREETEXT(Title, #FTSSearchTerm)
AND WebsiteID = #WebsiteID
AND ContentTypeID = #ContentTypeID
AND GeoID2 = #GeoID
)
SELECT #ActualNumberOfResults = COUNT(*)
FROM Results1

Related

Postgresql nested select max(sum())

My Query:
select table.attribute, count(table.attribute) AS cnt from table
group by table.attribute
order by cnt desc;
The output is something like:
attribute | cnt
-----------+-----
A | 2
B | 2
G | 1
F | 1
But i only want the max values (A & B).
You can do this with a single level of nesting:
select attribute,
cnt
from (
select attribute,
count(*) AS cnt,
max(count(*)) over () as max_cnt
from t
group by attribute
) t
where cnt = max_cnt;
You can use the power of CTE to achieve this:
WITH count_values
AS (SELECT table.attribute,
Count(table.attribute) AS cnt
FROM table
GROUP BY table.attribute),
max_values
AS (SELECT Max(cnt) AS max_cnt
FROM (SELECT cnt
FROM count_values) sub)
SELECT *
FROM count_values cv
JOIN max_values mv
ON mv.max_cnt = cv.cnt;
you can use rank as below
with cte as (
select *, Rank() over(order by cnt desc) as rnk from yourattribute
) select * from cte where rnk = 1

Creating a Void Function in PostgreSQL

I am getting an error on this create function code in Postgresql. The error says it is happening around Line 2 at DELETE, but it happens at WITH if I remove that line so I think it is a problem with the format of my Creat Function
create or replace function retention_data(shopId integer) returns void as $$
delete from retention where shop_id = shopId;
WITH ret_grid_step1 as (
select * from (
SELECT
order_id as order_name,
cust_name as cust_name,
email as email,
date(order_date) as created_at,
count(*) as num_items_in_order,
sum(total_price) as sales ,
rank() over (partition BY order_id ORDER BY cust_name ASC) as rnk_shipping_name,
rank() over (partition BY order_id ORDER BY email ASC) as rnk_email
FROM orders
WHERE shop_id = shopId
and order_date is not null and order_date > now()::date - 365 and order_date < now()::date + 1
group by 1,2,3,4
) x
where rnk_shipping_name = 1 and rnk_email = 1
)
insert into retention(shop_id, cust_name, email, last_purchase_dt, total_sales, num_orders, days_since_last_order)
select
shopId as shop_id,
coalesce(b.cust_name,'null') as cust_name,
a.email,
a.last_purchase_dt,
total_sales,
num_orders,
current_date - last_purchase_dt as days_since_last_order
from (
select
email,
max(created_at) as last_purchase_dt,
count(*) as num_orders,
sum(sales) as total_sales
from ret_grid_step1
group by 1
) as a
left join (
select
email,
cust_name,
rank() over (partition BY email ORDER BY created_at DESC) as rnk
from ret_grid_step1
--where cust_name is not null
group by 1,2,created_at
) as b
on a.email = b.email
where b.rnk = 1
and a.email <> '';
$$ language plpgsql;

DATEDIFF On Dates

I've been struggling with this but I'm not really good at tsql.
This is what I got, and I can't have the DateTime calculates all right. I'm getting the sum between A and B but not the total sum. For example in the last column I have a 0 which is getting me back to -x.
Here is the procedure, and some of the data are like this:
Code_Procedure date_evenement codes_situation
---------------------------------------------------------------
000079500000 2013-05-21 13:07:00.000 COMCFM
000079500000 2013-05-21 20:24:00.000 PCHCFM
000079500000 2013-05-22 09:58:00.000 PCHCFM
000079500000 2013-05-23 00:00:00.000 AARCFM
000079500000 2013-05-23 00:00:00.000 LIVCFM
000079600000 2013-05-21 13:07:00.000 COMCFM
000079600000 2013-05-21 20:24:00.000 PCHCFM
000079600000 2013-05-22 11:18:00.000 PCHCFM
000079600000 2013-05-23 00:00:00.000 AARCFM
000079600000 2013-05-23 00:00:00.000 LIVCFM
Here is the proc:
DECLARE #COMCFM TABLE(numero_colis VARCHAR(25), date_evenement DATETIME);
INSERT #COMCFM SELECT TOP(5) numero_colis, date_evenement FROM cartitem_colis_postaux_etats WHERE (code_situation = 'PCH' AND code_justification = 'CFM')
WHILE (SELECT COUNT(*) FROM #COMCFM) > 0
BEGIN
DECLARE #Colis TABLE(numero_colis VARCHAR(25), date_evenement DATETIME, code_situation_code_justification NVARCHAR(32));
INSERT #Colis SELECT numero_colis, date_evenement, code_situation + code_justification FROM cartitem_colis_postaux_etats WHERE numero_colis = (SELECT TOP(1) numero_colis FROM #COMCFM) ORDER BY numero_colis, date_evenement
;WITH CTE AS
(
Select DISTINCT
*
,ROW_NUMBER() OVER(PARTITION BY numero_colis ORDER BY date_evenement ASC) Rn FROM #Colis
),CTE1 AS
(
SELECT DISTINCT
A.*
,DATEDIFF(mi, B.date_evenement, A.date_evenement) AS DIFF
FROM CTE A INNER JOIN CTE B On B.Rn + 1 = A.Rn
UNION All
SELECT A.*, 0 FROM CTE A Where Rn = 1
)
SELECT
A.*
,ISNULL((
SELECT
A.DIFF + B.DIFF
FROM CTE1 AS B
WHERE A.numero_colis = B.numero_colis
AND A.Rn = B.Rn + 1), 0) AS Sums
FROM CTE1 AS a
ORDER BY numero_colis, Rn ASC
DELETE FROM #Colis
DELETE FROM #COMCFM WHERE numero_colis = (SELECT TOP(1) numero_colis FROM #COMCFM)
END
I'm not really sure what you would like to achieve. Do you need date differencies as a cummulated value? If you need this, change your BEGIN-END block of your stored procedure with this code
BEGIN
DECLARE #Colis TABLE(numero_colis VARCHAR(25), date_evenement DATETIME, code_situation_code_justification NVARCHAR(32));
INSERT #Colis SELECT numero_colis, date_evenement, code_situation + code_justification FROM cartitem_colis_postaux_etats WHERE numero_colis = (SELECT TOP(1) numero_colis FROM #COMCFM) ORDER BY numero_colis, date_evenement
;WITH CTE AS
(
SELECT DISTINCT
*,
ROW_NUMBER() OVER(PARTITION BY numero_colis ORDER BY date_evenement ASC) Rn
FROM #Colis
),CTE1 AS
(
SELECT A.*, 0 AS CummulatedDiff
FROM CTE A
WHERE Rn = 1
UNION ALL
SELECT DISTINCT A.*, B.CummulatedDiff + DATEDIFF(mi, B.date_evenement, A.date_evenement) AS CummulatedDiff
FROM CTE AS A INNER JOIN
CTE1 AS B ON B.Rn + 1 = A.Rn AND B.numero_colis = A.numero_colis
)
SELECT *
FROM CTE1 AS a
ORDER BY numero_colis, Rn ASC
DELETE FROM #Colis
DELETE FROM #COMCFM WHERE numero_colis = (SELECT TOP(1) numero_colis FROM #COMCFM)
END
I hope this takes you further to your goal.

How to set the “Order” of Items in a hierarchy table in an easier and shorter way?

Refering to this post, here is the overall question and codes:
declare #tbl table (MenuItemID uniqueidentifier, PID uniqueidentifier, MenuID uniqueidentifier, SO tinyint, lvl tinyint)
;WITH
cte (MenuItemID, PID, MenuID, SO, lvl) AS
(
select MenuItemID, PID, MenuID, SO, 0 from MenuItems
where del = 0 and Perms = 1 and MenuID = #MenuID and MenuID = PID
UNION ALL
SELECT MenuItems.MenuItemID, MenuItems.PID, MenuItems.MenuID, MenuItems.SO, cte.lvl + 1 FROM MenuItems
JOIN cte ON cte.MenuItemID = MenuItems.PID
)
select * from cte
ORDER BY lvl, SO
insert into #tbl select * from cte
declare #tbl2 table (MenuItemID uniqueidentifier, PID uniqueidentifier, MenuID uniqueidentifier, SO tinyint, lvl tinyint)
;with hier (MenuItemID, PID, MenuID, SO, lvl, FullSO) as
(select l0.*, convert(varchar(max),right('000'+convert(varchar(3),SO),3)) FullSO
from #tbl l0 where lvl=0
union all
select ln.*, lp.FullSO+','+right('000'+convert(varchar(3),ln.SO),3) FullSO
from #tbl ln
join hier lp on ln.PID = lp.MenuItemID)
insert into #tbl2
select MenuItemID,
PID,
MenuID,
rank() over (partition by PID order by SO) SO,
lvl
from hier
order by FullSO, SO
update MenuItems set SO = h.SO
from MenuItems as mi
join #tbl2 h on mi.MenuItemID = h.MenuItemID and mi.MenuID = h.MenuID
I'd like to know whether there is an easier and shorter way for this code?
Thanks in advance,
Kardo
You will still need a recursive CTE to determine which top-level records for the hierarchy have del = 0 and Perms = 1, but the following should be simpler:
WITH cte AS
(select MenuItemID, PID, MenuID, SO,
rank() over (partition by PID order by SO) newSO
from MenuItems
where del = 0 and Perms = 1 and MenuID = #MenuID and MenuID = PID
UNION ALL
SELECT m.MenuItemID, m.PID, m.MenuID, m.SO,
rank() over (partition by m.PID order by m.SO) newSO
FROM MenuItems m
JOIN cte c ON c.MenuItemID = m.PID
)
update MenuItems set SO = h.newSO
from MenuItems as mi
join cte h on mi.MenuItemID = h.MenuItemID and mi.MenuID = h.MenuID;
SQLFiddle here.

t-sql WITH on WITH

I have to make query on WITH query, something like
; WITH #table1
(
SELECT id, x from ... WHERE....
UNION ALL
SELECT id, x from ... WHERE...
)
WITH #table2
(
SELECT DISTINCT tbl_x.*,ROW_NUMBER() OVER (order by id) as RowNumber
WHERE id in ( SELECT id from #table1)
)
SELECT * FROM #table2 WHERE RowNumber > ... and ...
So I have to use WITH on WITH and then SELECT on second WITH, How I can do that?
You can define multiple CTEs after the WITH keyword by separating each CTE with a comma.
WITH T1 AS
(
SELECT id, x from ... WHERE....
UNION ALL
SELECT id, x from ... WHERE...
)
, T2 AS
(
SELECT DISTINCT tbl_x.*, ROW_NUMBER() OVER (order by id) as RowNumber
WHERE id in ( SELECT id from T1 )
)
SELECT * FROM T2 WHERE RowNumber > ... and ...
https://web.archive.org/web/20210927200924/http://www.4guysfromrolla.com/webtech/071906-1.shtml