So I'm trying to do something like this:
Ex Table:
id, Name, To
1, A, 2
2, B, 0
3, C, 2
4, D, 0
5, E, 1
Expected results:
id, Name, To, Count
1, A, 2, 1
2, B, 0, 2
3, C, 2, 0
4, D, 0, 0
5, E, 1, 0
Here I'm trying to get a count of rows being referenced each time. For example row with id 1 is referenced once in a row with id 5, similarly row with id 2 is referenced twice in rows with id 1 and id 3.
This is what I have tried:
select *
from sample
left join(
select "to", count(*)
from sample
group by "to") j on j."to" = sample."id"
and this is what I'm getting:
Results:
id, Name, To, Count
1, A, 1, 1
2, B, 2, 2
3, C, null,null
4, D, null,null
5, E, null,null
Any ideas how I can make this work?
Found the solution. I ended up using a correlated query.
select *,
(select count(to)
from sample s
where s.to = sample.id
) as ct
from sample;
Thanks to: Gordon Linoff's Answer
Related
I have this SQL Server table table1 which I want to fill with dummy rows per acct up to latest previous month end date period e.g now would be up to 2021-06-30.
In this example, acct 1 has n number of rows which ends at 2020-05-31, and I want to insert dummy rows with same values for acct and amt with begin_date and end_date incrementing by 1 month up to 06-30-2021.
Let's assume acct 2 already ends at 06-30-2021 so this doesn't need dummy rows to be inserted.
acct,amt,begin_date,end_date
1 , 10, 2020-04-01, 2020-04-30
1 , 10, 2020-05-01, 2020-05-31
2 , 50, 2021-05-01, 2021-05-31
2 , 50, 2021-06-01, 2021-06-30
So for acct 1, I want n number of rows to be inserted from last period of 2020-05-31 up to previous month end which is now 06-30-2021 and I want the amt and acct to remain same. So it would look like this below:
acct,amt,begin_date,end_date
1 , 10, 2020-04-01, 2020-04-30
1 , 10, 2020-05-01, 2020-05-31
1 , 10, 2020-06-01, 2020-06-30
1 , 10, 2020-07-01, 2020-07-31
.............................
.............................
1 , 10, 2021-06-01, 2021-06-30
Based on some data anamolies, I realize I need another condition to the solution. Suppose another column type was added to the table1. So acct and type would be the composite key that identifies each related row hence acct 2 type A and acct 2 type B are not related. So we have the updated table:
acct,type,amt,begin_date,end_date
1, A, 10, 2020-04-01, 2020-04-30
1, A, 10, 2020-05-01, 2020-05-31
2, A, 50, 2021-05-01, 2021-05-31
2, A, 50, 2021-06-01, 2021-06-30
2, B, 50, 2021-01-01, 2021-01-31
2, B, 50, 2021-02-01, 2021-02-28
I would now need dummy rows to be created for acct 2 type B up to 2021-06-30. We already know acct 2 type A would be ok since it already has rows up to 2021-06-30
You can generate the rows using a recursive CTE:
with cte as (
select acct, amt,
dateadd(day, 1, end_date) as begin_date,
eomonth(dateadd(day, 1, end_date)) as end_date
from (select t.*,
row_number() over (partition by acct order by end_date desc) as seqnum
from t
) t
where seqnum = 1 and end_date < '2021-06-30'
union all
select acct, amt, dateadd(month, 1, begin_date),
eomonth(dateadd(month, 1, begin_date))
from cte
where begin_date < '2021-06-01'
)
select *
from cte;
You can then use insert to insert these rows into a table. Or use union all if you simply want a result set with all the rows.
Here is a db<>fiddle.
I am working on a query to find all orders that have had all the necessary modifications completed and the work item where the last modification was complete. The table that keeps track of all work done on the order can have multiple entries per item. And no, I unfortunately do not have the ability to modify the schema.
Orders Table:
OrderId(int), CustomerId(int), OrderDate(DateTime)
1, 58, '2021-01-01'
2, 75, '2021-01-01'
3, 78, '2021-01-01'
4, 50, '2021-01-01'
Work Table:
WorkId(int), OrderId(int), Mod1Completed(bit), Mod2Completed(bit), Mod3Completed(bit), ModDate (DateTime), ModBy (int)
1005, 1, 0, 1, 1, '2021-02-01', 685
1006, 1, 1, 1, 0, '2021-02-03', 875
1007, 2, 0, 1, 0, '2021-02-01', 211
1008, 3, 1, 1, 1, '2021-01-15', 669
Sample output:
1006, 1, 1, 1, 0, '2021-02-03', 875
1008, 3, 1, 1, 1, '2021-01-15', 669
I have the following query that I think is correct (still testing) but it seems clunky and am trying to improve it. For what it's worth, the Work table is regularly purged and would not have massive amounts of data (most likely < 100 rows at any particular time)
WITH AnySuccessful AS(
SELECT * FROM Work WITH (NOLOCK) WHERE Mod1Completed = 1
OR Mod2Completed = 1
OR Mod3Completed = 1
),
SuccessfulCount AS(
SELECT OrderId,
MAX(s.ModDate) AS ModDate ,
Max(CAST(Mod1Completed as int)) + Max(CAST(Mod2Completed as int)) + Max(CAST(Mod3Completed as int)) AS Successes
FROM AnySuccessful s
GROUP BY OrderId
),
AllSuccessful AS(
Select S.OrderId, WorkID, sc.Successes From AnySuccessful S
Inner Join SuccessfulCount sc on s.OrderId=sc.OrderId and s.ModDate = sc.ModDate AND sc.Successes=3
)
Select w.* from Work w
inner join AllSuccessful ASF on W.OrderId = ASF.OrderId AND W.WorkId = ASF.WorkId
SQLFiddle
This might be easier to follow.. assuming the workid and moddate are always in order
select OrderId
, max(WorkId) as WorkId
, max(convert(int, Mod1Completed)) as Mod1Completed
, max(convert(int, Mod2Completed)) as Mod2Completed
, max(convert(int, Mod3Completed)) as Mod3Completed
, max(ModDate) as ModDate
from Work
group by OrderId
having max(convert(int, Mod1Completed)) + max(convert(int, Mod2Completed)) + max(convert(int, Mod3Completed)) = 3
I am trying to perform a filtering operation in SQL Server 2005.
Example. Let's say we have two tables, Current and Reject.
Current = 1, 2, 3, 4, 5, 1, 2
Reject = 2, 3, 4
Current \ Reject = 1, 2, 5
As you can see, the two tables share values. I essentially just want to subtract those shared values and place them into a new table.
This is what I tried, but it didn't work. (A is the column to match on).
select * from Current left join
Reject on csrp.a = rp.a
group by Current.a, Reject.a
having count(Current.a) > count(Reject.a)
Notice below that the element 2 was filtered out, even though it should not have been.
Martin Smith's answer worked for this case!
EDIT
Ok, so let's complicate it a little bit more. Let's say I have the exact same situation as before, except this time I need to match on three columns instead of just one?
Current = (1, 2, 3), (2, 3, 4), (2, 3, 4), (4, 5, 6), (7, 8, 9), (1, 2, 3)
Reject = (2, 3, 4), (4, 5, 6), (7, 8, 9)
Current \ Reject = (1, 2, 3), (2, 3, 4)
WITH [Current](a, b, c)
AS (SELECT 1, 2, 3 UNION ALL
SELECT 2, 3, 4 UNION ALL
SELECT 2, 3, 4 UNION ALL
SELECT 4, 5, 6 UNION ALL
SELECT 7, 8, 9 UNION ALL
SELECT 1, 2, 3),
Reject(a, b, c)
AS (SELECT 2, 3, 4 UNION ALL
SELECT 4, 5, 6 UNION ALL
SELECT 7, 8, 9 ),
T(RN, a, b, c)
AS (SELECT ROW_NUMBER() OVER (PARTITION BY a, b, c ORDER BY (SELECT 0)),
a,
b,
c
FROM [Current]
EXCEPT
SELECT ROW_NUMBER() OVER (PARTITION BY a, b, c ORDER BY (SELECT 0)),
a,
b,
c
FROM Reject)
SELECT DISTINCT a,
b,
c
FROM T
I have 2 SQL Server 2005 tables: Names and Scores
Names table:
NameID, Name, Age
1, 'John', 23
2, 'Ryan', 20
Scores table:
ScoreID, NameID, ScoreDate, ScoreValue
1, 1, 01/01/2011, 250
2, 1, 02/01/2011, 300
3, 1, 03/01/2011, 100
4, 2, 01/01/2011, 150
5, 2, 02/01/2011, 350
6, 2, 03/01/2011, 200
I want to get for a given month:
Name, Age, current ScoreValue, sum(ScoreValue) for previous months
Something like this form the month of february:
John, 23, 300, 550
Ryan, 20, 350, 500
Think this is what you want:
select n.Name,
s1.ScoreId,
s1.nameId,
s1.ScoreValue,
sum(s2.ScoreValue) Prevmonths
from names n
inner join scores s1 on n.NameId = s1.NameId
left join scores s2 -- make left join in case no previous month
on s1.NameId = s2.NameId
and s1.ScoreDate >= s2.ScoreDate -- >= means include current onth
group by n.Name,
s1.ScoreId,
s1.nameId,
s1.ScoreValue
GJ
I have a set of hierarchical data that I'm hoping to get into the right format without using a loop. Maybe it's a long day and I just don't see how to do it.
When it starts the data looks like this:
(row = row ID, par = parent row ID, lev = level, has_child is obvious, had to do that or edit the space between all those numbers!)
row par lev has_child
1 NUL 0 1
2 1 1 1
3 1 1 1
4 1 1 1
5 1 1 1
6 1 1 0
148 2 2 0
149 2 2 1
145 3 2 0
146 3 2 1
9 4 2 0
11 4 2 0
12 4 2 0
13 4 2 0
14 4 2 0
15 4 2 0
16 4 2 0
17 4 2 0
I'd like it to be in a parent, child, child, child, ... order. So that all the children of a parent are shown before the next parent is started. Like this:
Parent
|
--- child L1
|
---- child L2
|
----- child L2
|
---- child L3
|
----- child L2
|
---- child L1
It seems like I should be able to accomplish this using ROW_NUMBER(), but I've been messing with it for a good half hour with no luck. Do I have to do this in a loop?
You can't with ROW_NUMBER(). You need to use a recursive CTE and create a synthetic sort order by composing the full parent path:
declare #table table (row int, par int, lev int, has_child bit);
insert into #table
select 1, NULL, 0, 1
union all select 2, 1, 1, 1
union all select 3, 1, 1, 1
union all select 4, 1, 1, 1
union all select 5, 1, 1, 1
union all select 6, 1, 1, 0
union all select 148, 2, 2, 0
union all select 149, 2, 2, 1
union all select 145, 3, 2, 0
union all select 146, 3, 2, 1
union all select 9, 4, 2, 0
union all select 11, 4, 2, 0
union all select 12, 4, 2, 0
union all select 13, 4, 2, 0
union all select 14, 4, 2, 0
union all select 15, 4, 2, 0
union all select 16, 4, 2, 0
union all select 17, 4, 2, 0;
with cte_anchor as (
select row, par, 0 as lev, cast(row as varchar(max)) as wbs
from #table
where par is null)
, cte_recursive as (
select row, par, lev, wbs
from cte_anchor
union all
select t.row, t.par, r.lev+1 as lev
, r.wbs + '.' + cast(t.row as varchar(max)) as wbs
from #table t
join cte_recursive r on t.par = r.row)
select * from cte_recursive
order by wbs
I have an example on this question (which is more complicated, but you'll get the idea)
SQL Server Tree Hierarchy and Nested Sets with Duplicate Record ids