Output multiple tables - sql

My SQL code generates a weekly file (let's call it #final) that I need to separate into 3 spreadsheets (subscribed, not subscribed and customers with no subscription status).
The #final table looks like this:
Member
IsSubscribed
001
NULL
002
1
003
NULL
004
0
I could easily export the table and filter the csv, but I want to automate this as much as possible.
I could simply write 3 SELECT statements and uncomment them as I need them, but I'm looking for a way to automatically produce three tables
--SELECT * FROM #final WHERE IsSubscribed = 1
--SELECT * FROM #final WHERE IsSubscribed = 0
--SELECT * FROM #final WHERE IsSubscribed IS NULL
My desired output:
TABLE 1
Member
IsSubscribed
002
1
TABLE 2
Member
IsSubscribed
004
0
TABLE 3
Member
IsSubscribed
001
NULL
003
NULL

I found the answer to my question was to create a temp table using INTO
SELECT
Member,
IsSubscribed
INTO #final
FROM <anothertable>
SELECT * FROM #final WHERE IsSubscribed = 1
SELECT * FROM #final WHERE IsSubscribed = 0
SELECT * FROM #final WHERE IsSubscribed IS NULL

Related

Row_Number in table with key where ordering does not make sense

I am using T-SQL.
I have a temporary table #t2 with only one column called internal.
Values of the column are n times a sequence from 1 to 3
i.e. : 1 2 3 1 2 3 1 2 3 ...
I want to add this column to another temporary table #t1 which only has a column of dates called Date (assuming that the number of rows of the two table is the same).
If I want to use a join, I need an on clause, but I do not have any key that would make sense. Moreover, cross join does not work since multiplies the number of columns. Hence, I thought to add a row_number to each table and inner join on the newly formed row_number columns.
However, row_number requires an order by clause and while #t1 contains the column Date which makes sense to sort on, table #t2 does not, so the row_number solution does not work either.
I tried to add a column id to table #t2 and add a row_number using a while loop but the column id is only populated by NULL values.
ALTER TABLE #t2
ADD id integer;
declare #iterFlag integer
declare #iteration2 integer
set #iteration2 = (select count(internal) from #t2)
--print #iteration2
set #intFlag = 1
while (#intFlag <= #iteration2)
begin
INSERT INTO #t2 (id)
VALUES (#intFlag)
SET #intFlag = #intFlag + 1
end;
go
If instead of using
INSERT INTO #t2 (id)
VALUES (#intFlag)
I use:
UPDATE #t2
SET id = #intFlag
then I only get the result of (select count(internal) from #t2).
Do you have any solution that would make me stack the two columns one next to each other?
As far as concerned your requirement boils down to: assign a number between 1 and 3 to each record in #t2. For this, you don't need table #t1, you can just use row_number():
alter table #t2 add id integer;
with cte as (select id, row_number() over(order by date) - 1 rn from #t2)
update cte set id = 1 + rn % 3;
This will assign a value between 1 and 3 to column id for each record in #t2, ordered by increasing date.
Demo on DB Fiddle:
create table #t2 (date datetime);
insert into #t2 values
('2020-01-01'),
('2020-01-02'),
('2020-01-03'),
('2020-01-04'),
('2020-01-05'),
('2020-01-06'),
('2020-01-07');
-- 7 rows affected
alter table #t2 add id integer;
with cte as (select id, row_number() over(order by date) - 1 rn from #t2)
update cte set id = 1 + rn % 3;
-- 7 rows affected
select * from #t2 order by date;
date | id
:---------------------- | -:
2020-01-01 00:00:00.000 | 1
2020-01-02 00:00:00.000 | 2
2020-01-03 00:00:00.000 | 3
2020-01-04 00:00:00.000 | 1
2020-01-05 00:00:00.000 | 2
2020-01-06 00:00:00.000 | 3
2020-01-07 00:00:00.000 | 1

How to update a field's value by an incremental value without using loop in SQL Server 2008?

I have a table #temp in SQL Server 2008 like this:
Id p_id h_no f_id
------------------
1 100 A01 null
2 200 A02 null
3 300 A02 null
4 400 null null
5 500 null null
6 600 A03 null
7 700 A01 null
8 400 null null
So basically, every record has a p_id, but may or may not have h_no.
What I want is to replace f_id values with a dummy incremental number based on:
if h_no value of a record matches another(s), this (those) ones will have same f_id (check ids:1 & 7 or ids:2 & 3 in the example)
if h_no is null but p_id values are equal for some cases, they will have same f_id (check ids: 4 & 8 in the example)
For example, the sample table above should be:
Id p_id h_no f_id
-----------------
1 100 A01 1
2 200 A02 2
3 300 A02 2
4 400 null 3
5 500 null 4
6 600 A03 5
7 700 A01 1
8 400 null 3
I do not want to use a loop for this process. I am trying to find a more optimal solution for this. I need a query something like below, could not find the correct syntax.
declare #tempFID int = 1;
update t
set t.f_id = #tempFID++ --syntax error
from #temp t
inner join #temp t2 on t.Id = t2.Id
where (t.h_no is not null and t.h_no = t2.h_no)
or (t.h_no is null and t.p_id = t2.p_id)
I also tried but had syntax error:
update t
set t.f_id = (set #tempFID = #tempFID + 1) --syntax error
...
Any help would be so appreciated!
;WITH cte AS (
SELECT *
,CASE WHEN h_no IS NULL THEN p_id ELSE MIN(p_id) OVER (PARTITION BY h_no) END as PIdGroup
FROM
#Table
)
, cteFIdValue AS (
SELECT
Id
,DENSE_RANK() OVER (ORDER BY PIdGroup) as f_id
FROM
cte
)
UPDATE t
SET f_id = u.f_id
FROM
Table t
INNER JOIN cteFIdValue u
ON t.ID = u.ID
Find the minimum p_id for each h_no and just leave it as the assigned p_id if h_no is null
Then create a dense rank on the PidGroup
Update the Table
so you have problems besides a syntax error in your code above. First your join will only get the exact same record, you would have to change to t.ID <> t2.ID as left join and still need some sort of ranking. honestly I am not positive what you are attempting there.
This approach might be simpler:
update #temp
set f_id = isnull(f_id, 0) +
case when condition1 is met then value 1
etc
when final condition is met then 0
else null
end

Sql Query to find reporting user details

i have a table with follow fields
UserID UserName ReportingUserID
1 Vinoth Null
2 Kumar 1
3 Raja 1
4 Ragu 2
5 Vignesh 2
6 Yoga 3
7 Yogesh 2
8 Eswar 4
9 Esakki 3
. ... .
. .... .
if i gave UserID as 1 then a query will display all users reporting to him will be displayed
if i gave USeRID as 1
Then result will be
UserID UserName ReportingUserID
2 Kumar 1
3 Raja 1
4 Ragu 2
5 Vignesh 2
6 Yoga 3
7 Yogesh 2
8 Eswar 4
9 Esakki 3
. ... .
. .... .
Have a look at using a recursive CTE.
A common table expression (CTE) can be thought of as a temporary
result set that is defined within the execution scope of a single
SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement. A CTE is
similar to a derived table in that it is not stored as an object and
lasts only for the duration of the query. Unlike a derived table, a
CTE can be self-referencing and can be referenced multiple times in
the same query.
Something like
DECLARE #Table TABLE(
UserID INT,
UserName VARCHAR(20),
ReportingUserID INT
)
INSERT INTO #Table VALUES
(1,'Vinoth',Null),
(2,'Kumar',1),
(3,'Raja',1),
(4,'Ragu',2),
(5,'Vignesh',2),
(6,'Yoga',3),
(7,'Yogesh',2),
(8,'Eswar',4),
(9,'Esakki',3)
DECLARE #UserID INT = 1
;WITH ReportingUsers AS (
SELECT *
FROM #Table
WHERE ReportingUserID = #UserID
UNION ALL
SELECT t.*
FROM #Table t INNER JOIN
ReportingUsers ru ON ru.UserID = t.ReportingUserID
)
SELECT *
FROM ReportingUsers

Using a Cursor to Update Rows in Single Table

I am seeking guidance using MS SQL cursor or SQL while loop to merge (add, update, and set inactive) rows using single table based on criteria below resulting in seeking the final dataset:
TABLE VIEW (SELECT * FROM TABLE WHERE ENTITY = 123 (#ID)
ENTITY ENTITY_TYPE VALUE STATUS_TYPE
123 1 1 1
123 1 4 1
123 1 9 1
TABLE VIEW (SELECT * FROM TABLE WHERE ENTITY = 456 (#OverrideID)
ENTITY ENTITY_TYPE VALUE STATUS_TYPE
456 1 1 1
456 1 5 1
Final Data Set below:
ENTITY&nbsp&nbsp&nbspTYPE VALUE STATUS_TYPE
123 1 1 3
123 1 4 3
123 1 9 3
456 1 1 1
456 1 4 1
456 1 9 1
456 1 1 1
456 1 5 1
-- Check and compare each row
-- IF #OverrideID = #ID (MATCH)
----- Set #ID to inactive keeping copy
-- If #OverrideID != #ID (NOT MATCH)
----- Insert #ID data with #OverrideID (COPY)
----- Set #ID to inactive.
I began writing the following and need help. For reference, #ID = 123 and #OverrideID = 456
DECLARE #ENTITY BIGINT, #ENTITY_TYPE BIGINT, #VALUE BIGINT, #E1 BIGINT, #T1 BIGINT, #V1 BIGINT
DECLARE type_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT * FROM TypeValue WHERE ENTITY = #ID
SET NOCOUNT OFF
OPEN type_cursor
FETCH NEXT FROM type_cursor INTO #OverrideID, #ID, #ENTITY, #ENTITY_TYPE, #VALUE
WHILE (##FETCH_STATUS = 0)
BEGIN
SELECT #ENTITY, #ENTITY_TYPE, #VALUE
IF #VALUE IS NOT NULL
BEGIN
SELECT #T1 = #ENTITY_TYPE, #V1 = #VALUE
END
ELSE
BEGIN
UPDATE TypeValue
SET ENTITY = #OverrideID, ENTITY_TYPE = #T1, VALUE = #V1 WHERE ENTITY = #ID
END
FETCH NEXT FROM type_cursor INTO #OverrideID, #ID, #ENTITY, #ENTITY_TYPE, #VALUE
END
CLOSE type_cursor
DEALLOCATE type_cursor
SET NOCOUNT OFF
That final result set looks like
select entity,entity_type,value,3 status_type
from [table]
where entity = #id
union all
select #override,entity_type,value,status_type
from [table]
where entity = #id
union all
select entity,entity_type,value,status_type
from [table]
where entity = #override

Update column value of one row from other rows

I have the following table:
sno name pid amount total
1 Arif 0 100 null
2 Raj 1 200 null
3 Ramesh 2 100 null
4 Pooja 2 100 null
5 Swati 3 200 null
6 King 4 100 null
I want total of each person such that it gives total sum of amount of its descendants.
For ex.
for RAJ total will be : total= amount of(raj+ramesh+pooja+swati+king)
for SWATI :Total=amount of swati only.
You could try something like this:
WITH hierarchified AS (
SELECT
sno,
amount,
hierarchyID = CAST(sno AS varchar(500))
FROM yourTable
WHERE pid = 0
UNION ALL
SELECT
t.sno,
t.amount,
hierarchyID = CAST(h.hierarchyID + '/' + RTRIM(t.sno) AS varchar(500))
FROM yourTable t
INNER JOIN hierarchified h ON t.pid = h.sno
)
UPDATE yourTable
SET total = t.amount + ISNULL(
(
SELECT SUM(amount)
FROM hierarchified
WHERE hierarchyID LIKE h.hierarchyID + '/%'
),
0
)
FROM yourTable t
INNER JOIN hierarchified h ON t.sno = h.sno;
Note that this query (which you can try on SQL Fiddle) would probably not be very efficient on a large dataset. It might do as a one-off query, and then it would likely be better to organise updating the totals each time the table is updated, i.e. using triggers.