MSSQL subquery result to show and calculate - sql-server

I need show a subquery result and use this same result to calculate other value, is possible set this value in a variable in MS SQL 2008 or something like this?
exemple:
SELECT
#test = (SELECT COUNT(*) FROM [tableTest] WHERE [tableTest].[columnA] = [tableA].[columnA]) as 'Counter'
, (#test * 50) as 'Calc'
, [tableA].[columnA]
FROM tableA

you may use a cte and join on it.
with cte as (select count(*) cnt, columnA from [tableTest] group by columnA)
select
c.cnt as 'Counter',
c.cnt * 50 as 'Calc',
a.columnA
from tableA a
join cte c on c.columnA = a.columnA
It could also be done with a subquery, of course
select
a.columnA,
c.cnt as 'Counter',
c.cnt * 50 as 'Calc'
from tableA a
join (select columnA, count(*) as cnt
from tableTest
group by columnA) c
on c.columnA = a.columnA

Why can't you do this. Move the subquery outside of select statement and store the result in a variable
Then use that variable for calculations.
declare #test int = (SELECT COUNT(*) FROM [tableTest])
SELECT
#test as 'Counter'
, (#test * 50) as 'Calc'
, [tableA].[columnA]
FROM tableA
Update :
SELECT [Counter],
( [Counter] * 50 ) AS 'Calc',
columnA
FROM (SELECT (SELECT Count(*)
FROM [tableTest]
WHERE [tableTest].[columnA] = [tableA].[columnA]) AS 'Counter',
[tableA].[columnA]
FROM tableA) A

You can also use correlated sub-queries:
SELECT
Counter = (SELECT COUNT(*) FROM tableTest t WHERE t.columnA = a.columnA),
Calc = (SELECT COUNT(*) FROM tableTest t WHERE t.columnA = a.columnA) * 50,
a.columnA
FROM tableA a
It'll be optimized to be only evaluated once.

Try:
SELECT t2.[Count]
,t2.[Count] * 50 As [Calc]
,[tableA].[columnA]
FROM TableA
CROSS APPLY
(
SELECT COUNT(*) AS [Count]
FROM TableTest
WHERE [tableTest].[columnA] = [tableA].[columnA]
) t2

Related

How to update a table rows with the pattern from first 10 records (similar to what fill handle in excel)

I want to update the below table where name is null to repeat the pattern from first 10 rows.
enter image description here
sql:
declare #name varchar(255)
set #name = select distinct name from #temp
update #temp
set name = #name
where name is not null
Obviously the above the query will not work due to multiple values. I want to update the table where it's null to fill with the pattern from above.
While I agree with Damien's suggestion that you not conflate databases and spreadsheets, you can do this quite easily with window functions and the modulo operator:
WITH x AS
(
SELECT dt,
name,
seq = ROW_NUMBER() OVER (ORDER BY dt),
c = COUNT(*) OVER()
FROM #temp
WHERE name IS NOT NULL
),
y AS
(
SELECT dt,
name,
seq = ROW_NUMBER() OVER (ORDER BY dt)
FROM #temp WHERE dt > (SELECT MAX(dt) FROM x)
)
UPDATE y SET y.name = x.name
FROM x INNER JOIN y
ON x.seq % x.c = y.seq % x.c;
Working example in this fiddle.
This doesn't validate, though, that the non-null values are all contiguous at the beginning - if you need the query to validate that, it's considerably more complicated.
I am just posting an Answer according to your picture.
I think if you want to use it some where else , then you should change it. (It is not General)
update
t1
set
t1.name = t2.name
from
(
select *,row_number() over (order by dt) - 1 as rn
from
(
select
*
from
tbl1
where
name is not null
)
as a
)
as t1
inner join
(
select
name,
day,
mod(rn, 10) as rn
from
(
select *,row_number() over (order by dt) - 1 as rn
from
(
select
*
from
tbl1
where
name is null
)
as b
)
as tmp
)
as t2
on t1.day = t2.day
and t1.rn = t2.rn

how to convert the result of many tables into one result

select sum(value) as sales_value_a from tbl_a
--its result =500
select sum(value) as sales_value_b from tbl_b
--its result =600
select sum(value) as sales_value_c from tbl_c
--its result =300
I want result like = tbl_a + tbl_b - tbl_c
--result =800
none of the queries i have tried are getting the right result. so i seek the humble cooperatiion of the experienced
SELECT (select sum(value) as sales_value_a from tbl_a) +
(select sum(value) as sales_value_b from tbl_b) +
(select sum(value) as sales_value_c from tbl_c) AS result
as mentioned in the comments union all then aggregate
with myTable(Value) as (
select Value from TableA union all
select Value from TableB union all
select Value from TableC
)
select sum(Value) from MyTable
http://sqlfiddle.com/#!18/e63f8/9
Try the below query to handle null. I have multiplied the result of table3 with (-1) as you want to subtract the result of 3rd Table.
SELECT SUM(value) result FROM
(
SELECT COALESCE(sum(value), 0) value FROM tbl_a
UNION
SELECT COALESCE(sum(value), 0) FROM tbl_b
UNION
SELECT (-1)*COALESCE(sum(value), 0) FROM tbl_c
)T
You can go for CROSS JOIN and apply your calculation as given below:
SELECT sum_a + sum_b -sum_c as totalsum
from
(
(select sum(value) as sales_value_a from tbl_a) as a(sum_a)
CROSS JOIN
(select sum(value) as sales_value_b from tbl_b) as b(sum_b)
CROSS JOIN
(select sum(value) as sales_value_c from tbl_c) as c(sum_c)
)
800

Unexpected result using CTE to perform a random join on two tables for all rows one-to-many

I am attempting to randomly join the rows of two tables (TableA and TableB) such that each row in TableA is joined to only one row in TableB and every row in TableB is joined to at least one row in TableA.
For example, a random join of TableA with 5 distinct rows and TableB with 3 distinct rows should result in something like this:
TableA TableB
1 3
2 1
3 1
4 2
5 1
However, sometimes not all the rows from TableB are included in the final result; so in the example above might have row 2 from TableB missing because in its place is either row 1 or 3 joined to row 4 on TableA. You can see this occur by executing the script a number of times and checking the result. It seems that it is necessary for some reason to use an interim table (#Q) to be able to ensure that a correct result is returned which has all rows from both TableA and TableB.
Can someone please explain why this is happening?
Also, can someone please advise on what would be a better way to get the desired result?
I understand that sometimes no result is returned due to a failure of some kind in the cross apply and ordering which i have yet to identify and goes to the point that I am sure there is a better way to perform this operation. I hope that makes sense. Thanks in advance!
declare #TableA table (
ID int
);
declare #TableB table (
ID int
);
declare #Q table (
RN int,
TableAID int,
TableBID int
);
with cte as (
select
1 as ID
union all
select
ID + 1
from cte
where ID < 5
)
insert #TableA (ID)
select ID from cte;
with cte as (
select
1 as ID
union all
select
ID + 1
from cte
where ID < 3
)
insert #TableB (ID)
select ID from cte;
select * from #TableA;
select * from #TableB;
with cte as (
select
row_number() over (partition by TableAID order by newid()) as RN,
TableAID,
TableBID
from (
select
a.ID as TableAID,
b.ID as TableBID
from #TableA as a
cross apply #TableB as b
) as M
)
select --All rows from TableB not always included
TableAID,
TableBID
from cte
where RN in (
select
top 1
iCTE.RN
from cte as iCTE
group by iCTE.RN
having count(distinct iCTE.TableBID) = (
select count(1) from #TableB
)
)
order by TableAID;
with cte as (
select
row_number() over (partition by TableAID order by newid()) as RN,
TableAID,
TableBID
from (
select
a.ID as TableAID,
b.ID as TableBID
from #TableA as a
cross apply #TableB as b
) as M
)
insert #Q
select
RN,
TableAID,
TableBID
from cte;
select * from #Q;
select --All rows from both TableA and TableB included
TableAID,
TableBID
from #Q
where RN in (
select
top 1
iQ.RN
from #Q as iQ
group by iQ.RN
having count(distinct iQ.TableBID) = (
select count(1) from #TableB
)
)
order by TableAID;
See if this gives you what you're looking for...
DECLARE
#CountA INT = (SELECT COUNT(*) FROM #TableA ta),
#CountB INT = (SELECT COUNT(*) FROM #TableB tb),
#MinCount INT;
SELECT #MinCount = CASE WHEN #CountA < #CountB THEN #CountA ELSE #CountB END;
WITH
cte_A1 AS (
SELECT
*,
rn = ROW_NUMBER() OVER (ORDER BY NEWID())
FROM
#TableA ta
),
cte_B1 AS (
SELECT
*,
rn = ROW_NUMBER() OVER (ORDER BY NEWID())
FROM
#TableB tb
),
cte_A2 AS (
SELECT
a1.ID,
rn = CASE WHEN a1.rn > #MinCount THEN a1.rn - #MinCount ELSE a1.rn end
FROM
cte_A1 a1
),
cte_B2 AS (
SELECT
b1.ID,
rn = CASE WHEN b1.rn > #MinCount THEN b1.rn - #MinCount ELSE b1.rn end
FROM
cte_B1 b1
)
SELECT
A = a.ID,
B = b.ID
FROM
cte_A2 a
JOIN cte_B2 b
ON a.rn = b.rn;

Using max(col) with count in sub-query SQL Server

I am putting together a query in SQL Server but having issues with the sub-query
I wish to use the max(loadid) and count the number of records the query returns.
So for example my last loadid is 400 and the amount of records with 400 is 2300, so I would my recor_count column should display 2300. I have tried various ways below but am getting errors.
select count (loadid)
from t1
where loadid = (select max(loadid) from t1) record_count;
(select top 1 LOADID, count(*)
from t1
group by loadid
order by count(*) desc) as Record_Count
Showing loadid and number of matching rows with the use of grouping, ordering by count and limiting the output to 1 row with top.
select top 1 loadid, count(*) as cnt
from t1
group by loadid
order by cnt desc
This may be easier to achieve with a window function in the inner query:
SELECT COUNT(*)
FROM (SELECT RANK() OVER (ORDER BY loadid DESC) AS rk
FROM t1) t
WHERE rk = 1
Another simplest way to achieve the result :
Set Nocount On;
Declare #Test Table
(
Id Int
)
Insert Into #Test(Id) Values
(397),(398),(399),(400)
Declare #Abc Table
(
Id Int
,Value Varchar(100)
)
INsert Into #Abc(Id,Value) Values
(398,'')
,(400,'')
,(397,'')
,(400,'')
,(400,'')
Select a.Id
,Count(a.Value) As RecordCount
From #Abc As a
Join
(
Select Max(t.Id) As Id
From #Test As t
) As v On a.Id = v.Id
Group By a.Id

Subtract result of two CTE

So I have a query like this
Create Procedure sp_GetTotalTargetsCount
#userId int
AS
Begin
Create Table #RequestTargets
(
Name varchar(20),
Value int
)
Declare #rId int
Set #rId=0
Select #rId=r.RequestId From Requests r
Join RequestPipeline rp
on r.RequestId=rp.RequestId
Join RequestStatus rs
on rp.RequestStatusId=rs.StatusId
Where rs.StatusDescription='In Progress.'
;With TotalCTE AS (Select Count(*) As TotalTargets FROM Targets Where InsertedByUserId=#userId),
FilteredCTE AS (Select Count(*) As FilteredTargets From RequestDetails Where RequestId=#rId)
Insert into #RequestTargets (Name,Value)
Select 'TotalTargets', Count(*) FROM Targets Where InsertedByUserId=#userId
Insert into #RequestTargets (Name,Value)
Select 'UnderSurveillence', Count(*) From
RequestDetails Where RequestId=#rId
Insert into #RequestTargets (Name,Value)
Values ('NotInSurveillence', (TotalCTE.TotalTargets-FilteredCTE.FilteredTargets)) --ERROR HERE it says Multipart identifier -- TotalTargets could not be bound
End
I think I can subract one count() query from the other count() without using CTE. Is there there a way to subtract the result of two CTE's as above. Please help.
You can't use CTE that way. Try
;WITH totalcte
AS (SELECT Count(*) AS TotalTargets
FROM targets
WHERE insertedbyuserid = #userId),
filteredcte
AS (SELECT Count(*) AS FilteredTargets
FROM requestdetails
WHERE requestid = #rId)
INSERT INTO #requesttargets
(NAME,
value)
SELECT 'NotInSurveillence',
totalcte.totaltargets - filteredcte.filteredtargets
FROM totalcte
CROSS JOIN filteredcte
FROM TotalCTE CROSS JOIN FilteredCTE
infact. . you can combine all into one big single query
;WITH totalcte
AS (SELECT Count(*) AS TotalTargets
FROM targets
WHERE insertedbyuserid = #userId),
filteredcte
AS (SELECT Count(*) AS FilteredTargets
FROM requestdetails
WHERE requestid = #rId)
INSERT INTO #requesttargets
(NAME,
value)
SELECT 'NotInSurveillence',
totalcte.totaltargets - filteredcte.filteredtargets
FROM totalcte
CROSS JOIN filteredcte
UNION ALL
SELECT 'TotalTargets',
totalcte.totaltargets
FROM totalcte
UNION ALL
SELECT 'UnderSurveillence',
filteredcte.filteredtargets
FROM filteredcte
select * from cte1 union distinct cte2

Resources