I have a Table :
Subject_ID StudyPlan_ID
271 2
279 2
276 2
279 8
271 8
267 9
279 9
I want to find the common Subject_ID between StudyPlan_ID so it's 279 using SqlServer 2008
So please any help.
If I understand it correctly, you mean find the Subject_ID that is linked to every StudyPlan_ID.
DECLARE #Data TABLE(Subject_ID int, StudyPlan_ID int)
INSERT INTO #Data
VALUES
(271, 2),
(279, 2),
(276, 2),
(279, 8),
(271, 8),
(267, 9),
(279, 9)
SELECT Subject_ID
FROM #Data AS a
GROUP BY Subject_ID
HAVING COUNT(Distinct StudyPlan_ID) = (SELECT COUNT(Distinct StudyPlan_ID) FROM #Data)
Related
There is several examples that concatenate string dealing with one single table. In my case I have two tables to take into account.
Table A
requestid int PK
Table B
requestid int
documentname varchar(50)
Table A requestid is of course unique, where table B requestid may have multiple lines. Table B can contain multiple relationship with the same requestid from table A. Also some of the Table A requestid might not have any associated records in table B.
I need to extract and join the two tables. Table A contains ~300k lines and table B contains ~140k lines. See the data below to illustrate what I need to achieve.
Table A sample
requestid FieldA FieldB FieldC
1 33 44 22
2 15 23 73
3 26 73 34
Table B sample
requestid documentname
1 firstdoc.doc
1 seconddoc.doc
1 thirddoc.doc
3 onedoc.doc
3 lastdoc.doc
Expected result:
requestid FieldA FieldB FieldC documentname
1 33 44 22 firstdoc.doc, seconddoc.doc, thirddoc.doc
2 15 23 73 NULL
3 26 73 24 onedoc.doc, lastdoc.doc
In my solution it is very important that requestid with no document associated to it are still in the result.
Hope my question is clear, thank you in advance.
This can be easily done with a stuff
See the example below
declare #tableA table (requestid int, fieldA int, fieldB int, fieldC int)
declare #tableB table (requestid int, documentname varchar(50))
insert into #tableA values (1, 33, 44, 22), (2, 15, 23, 73), (3, 26, 73, 34)
insert into #tableB values (1, 'firstdoc.doc'), (1, 'seconddoc.doc'), (1, 'thirddoc.doc'), (3, 'onedoc.doc'), (3, 'lastdoc.doc')
select a.requestid, a.fieldA, a.fieldB, a.fieldC,
stuff(( ( select ',' + b.documentname
from #tableB b
where b.requestid = a.requestid
order by 1
For XML PATH (''))
), 1, 1, '') as docname
from #tableA a
the result is
requestid fieldA fieldB fieldC docname
--------- ------ ------ ------ --------
1 33 44 22 firstdoc.doc,seconddoc.doc,thirddoc.doc
2 15 23 73
3 26 73 34 lastdoc.doc,onedoc.doc
Sample Data in Yellow the desired output
Just need your expert help on this.
I need to get the output based on T-SQL. Whenever the invoice_line_id_link is 0 put the product_id value if not look into the id column and get the product_id of that row.
Here's the script.
declare #t table
(id int, invoice_id int, product_id int, invoice_line_id_link int);
insert into #t values
(53,10,383,0),
(54,10,344,53),
(55,10,920,53),
(57,10,384,0),
(58,10,359,57),
(59,10,242,57),
(60,10,284,0);
select id, invoice_id, product_id,invoice_line_id_link, null desiredoutput from #t
based on the image if possible to populate using TSQL
Based on the image you have provided , here is the piece of code producing desired output.
Table Populate
declare #t table (id int, invoice_id int, product_id int, invoice_line_id_link int);
insert into #t values (53,10,383,0), (54,10,344,53), (55,10,920,53), (57,10,384,0), (58,10,359,57), (59,10,242,57), (60,10,284,0);
Code for Output
select *,CASE WHEN invoice_line_id_link = 0 THEN product_id
ELSE (select t1.product_id from #t t1 where t1.id = t2.invoice_line_id_link)
END from #t t2
Output
id invoice_id product_id invoice_line_id_link desiredoutput
53 10 383 0 383
54 10 344 53 383
55 10 920 53 383
57 10 384 0 384
58 10 359 57 384
59 10 242 57 384
60 10 284 0 284
*/
I have an existing database where some logic is made by the front end application.
Now I have to make reports from that database and I'm facing to a proble of missing records which are covered on a record basis in the frontend but have issues in the report
Given the following tables:
create table #T (id int, id1 int, label varchar(50))
create table #T1 (id int, T_id1 int, A int, B int, C int)
With the values:
insert into #T values (10, 1, 'label1'), (10, 2, 'label2'), (10, 3, 'label3'), (10, 15, 'label15'), (10, 16, 'label16'), (20, 100, 'label100'), (20, 101, 'label101')
insert into #T1 values (10, 1, 100, 200, 300), (10, 15, 150, 250, 350), (20, 100, 151, 251, 351), (20, 101, 151, 251, 351)
if I make a report we can see some missing records:
select #T.id, #T.id1, #T1.A, #T1.B, #T1.C
from #T left join #T1 on #T.id1 = #T1.T_id1
result:
id id1 A B C
10 1 100 200 300
10 2 NULL NULL NULL
10 3 NULL NULL NULL
10 15 150 250 350
10 16 NULL NULL NULL
20 100 151 251 351
20 101 151 251 351
Expected result would be:
id id1 A B B
10 1 100 200 300
10 2 100 200 300
10 3 100 200 300
10 15 150 250 350
10 16 150 250 350
20 100 151 251 351
20 101 151 251 351
As you can see here the missing data is filled out of the the first (in id, id1 order) previous existing record for a given id. For a given id there can be any number of "missing" records and for the given id there can be any number of existing records after a not existing ones.
I can do this with a cursor but I'm looking for a solution without cursor
You can use subquery (to find groups with same values) + window function
WITH Grouped AS (
SELECT #T.id, #T.id1, #T1.A, #T1.B, #T1.C,
GroupN = SUM(CASE WHEN #T1.A IS NULL THEN 0 ELSE 1 END) OVER(/* PARTITION BY id ? */ ORDER BY id1 ROWS UNBOUNDED PRECEDING)
FROM #T
LEFT JOIN #T1 ON #T.id1 = #T1.T_id1
)
SELECT Grouped.id, Grouped.id1,
A = MAX(A) OVER(PARTITION BY GroupN),
B = MAX(B) OVER(PARTITION BY GroupN),
C = MAX(C) OVER(PARTITION BY GroupN)
FROM Grouped
You can use below sql for thedesired output:
with cte (id, id1, A, B, C)
as
(
select #T.id, #T.id1, #T1.A, #T1.B, #T1.C
from #T left join #T1 on #T.id1 = #T1.T_id1
)
select cte.id, cte.id1,
coalesce(cte.A,TT.A) A,
coalesce(cte.B,TT.B) B,
coalesce(cte.C,TT.C) C
from cte
left join
(
select p.id1,max(q.id1) id1_max
from cte p
inner join cte q on p.id1 > q.id1 and p.a is null and q.a is not null
group by p.id1
) T on cte.id1 = T.id1
left join cte TT on T.id1_max = TT.id1
This is not a homework question.
I'm trying to take the count of t-shirts in an order and see which price range the shirts fall into, depending on how many have been ordered.
My initial thought (I am brand new at this) was to ask another table if count > 1st price range's maximum, and if so, keep looking until it's not.
printing_range_max printing_price_by_range
15 4
24 3
33 2
So for example here, if the order count is 30 shirts they would be $2 each.
When I'm looking into how to do that, it looks like most people are using BETWEEN or IF and hard-coding the ranges instead of looking in another table. I imagine in a business setting it's best to be able to leave the range in its own table so it can be changed more easily. Is there a good/built-in way to do this or should I just write it in with a BETWEEN command or IF statements?
EDIT:
SQL Server 2014
Let's say we have this table:
DECLARE #priceRanges TABLE(printing_range_max tinyint, printing_price_by_range tinyint);
INSERT #priceRanges VALUES (15, 4), (24, 3), (33, 2);
You can create a table with ranges that represent the correct price. Below is how you would do this in pre-2012 and post-2012 systems:
DECLARE #priceRanges TABLE(printing_range_max tinyint, printing_price_by_range tinyint);
INSERT #priceRanges VALUES (15, 4), (24, 3), (33, 2);
-- post-2012 using LAG
WITH pricerange AS
(
SELECT
printing_range_min = LAG(printing_range_max, 1, 0) OVER (ORDER BY printing_range_max),
printing_range_max,
printing_price_by_range
FROM #priceRanges
)
SELECT * FROM pricerange;
-- pre-2012 using ROW_NUMBER and a self-join
WITH prices AS
(
SELECT
rn = ROW_NUMBER() OVER (ORDER BY printing_range_max),
printing_range_max,
printing_price_by_range
FROM #priceRanges
),
pricerange As
(
SELECT
printing_range_min = ISNULL(p2.printing_range_max, 0),
printing_range_max = p1.printing_range_max,
p1.printing_price_by_range
FROM prices p1
LEFT JOIN prices p2 ON p1.rn = p2.rn+1
)
SELECT * FROM pricerange;
Both queries return:
printing_range_min printing_range_max printing_price_by_range
------------------ ------------------ -----------------------
0 15 4
15 24 3
24 33 2
Now that you have that you can use BETWEEN for your join. Here's the full solution:
-- Sample data
DECLARE #priceRanges TABLE
(
printing_range_max tinyint,
printing_price_by_range tinyint
-- if you're on 2014+
,INDEX ix_xxx NONCLUSTERED(printing_range_max, printing_price_by_range)
-- note: second column should be an INCLUDE but not supported in table variables
);
DECLARE #orders TABLE
(
orderid int identity,
ordercount int
-- if you're on 2014+
,INDEX ix_xxy NONCLUSTERED(orderid, ordercount)
-- note: second column should be an INCLUDE but not supported in table variables
);
INSERT #priceRanges VALUES (15, 4), (24, 3), (33, 2);
INSERT #orders(ordercount) VALUES (10), (20), (25), (30);
-- Solution:
WITH pricerange AS
(
SELECT
printing_range_min = LAG(printing_range_max, 1, 0) OVER (ORDER BY printing_range_max),
printing_range_max,
printing_price_by_range
FROM #priceRanges
)
SELECT
o.orderid,
o.ordercount,
--p.printing_range_min,
--p.printing_range_max
p.printing_price_by_range
FROM pricerange p
JOIN #orders o ON o.ordercount BETWEEN printing_range_min AND printing_range_max
Results:
orderid ordercount printing_price_by_range
----------- ----------- -----------------------
1 10 4
2 20 3
3 25 2
4 30 2
Now that we have that we can
this is the given tables data ,i want the output like this as given by me .
slno name salary
-----------------------------
1 raj 5000.0000
2 laba 4000.0000
3 silu 3000.0000
4 jaya 6000.0000
5 papu 7000.0000
6 tikan 9000.0000
7 susanta 6000.0000
8 chiku 4500.0000
9 micky 5500.0000
10 susa 2500.0000
11 musa 6500.0000
12 pi 6500.0000
13 luna 7500.0000
14 tuna 9500.0000
15 tina 3500.0000
Desired output
slno name salary
----------------------
1 raj 5000.0000
2 laba 4000.0000
3 silu 3000.0000
4 jaya 6000.0000
5 papu 7000.0000
6-10 ---- 27500.0000(total salary from 6-10)
6-15 ---- 61000.0000(total salary from 6-15)
Try this:
create table #table_name (slno int, name varchar(20), salary float);
insert into #table_name (slno, name, salary) values
(1, 'raj', 5000.0000),
(2, 'laba', 4000.0000),
(3, 'silu', 3000.0000),
(4, 'jaya', 6000.0000),
(5, 'papu', 7000.0000),
(6, 'tikan', 9000.0000),
(7, 'susanta', 6000.0000),
(8, 'chiku', 4500.0000),
(9, 'micky', 5500.0000),
(10, 'susa', 2500.0000),
(11, 'musa', 6500.0000),
(12, 'pi', 6500.0000),
(13, 'luna', 7500.0000),
(14, 'tuna', 9500.0000),
(15, 'tina', 3500.0000);
select cast(slno as varchar(10)) [slno]
, name
, salary
from #table_name where slno <= 5
union all
select '6-10'
, '----'
, sum(salary)
from #table_name where slno between 6 and 10
union all
select '6-15'
, '----'
, sum(salary)
from #table_name where slno between 6 and 15
Result
slno name salary
----------------------
1 raj 5000
2 laba 4000
3 silu 3000
4 jaya 6000
5 papu 7000
6-10 ---- 27500
6-15 ---- 61000