combining multiple queries / query optimization - sql-server

I have made a little example data that I modify in three steps. I cant do it in one, maybe there is a clever way with some logic? I use Microsoft SQL Server
This code will generate the four base tables with example data and the step by step queries I want to combine, the result at the end should have 8 entries:
Reference table:
CREATE TABLE ref
(
ID int NOT NULL
NR int NOT NULL
CONSTRAINT KEYS PRIMARY KEY (ID, NR)
);
INSERT INTO ref
VALUES (1234, 223), (1234, 224), (1234, 225),
(1235, 123), (1235, 124), (1236, 540),
(1236, 541), (1237, 233), (1237, 234);
Con1 table:
CREATE TABLE con1
(
NR int NOT NULL
flag int NOT NULL
PRIMARY KEY (NR)
);
INSERT INTO con1
VALUES (123, 0), (124, 1), (125, 0),
(220, 0), (222, 0), (223, 0),
(224, 0), (225, 1), (300, 0),
(540, 1), (541, 1);
Con2 table:
CREATE TABLE con2
(
NR int NOT NULL
ID int NOT NULL
PRIMARY KEY (NR)
);
INSERT INTO con2
VALUES (123, 1235), (124, 1235), (125, 1243),
(220, 1296), (222, 1255), (223, 1234),
(224, 1234), (225, 1234), (300, 1267),
(540, 1236);
Info table:
CREATE TABLE info
(
NR int NOT NULL
SNR int NOT NULL
SSNR int NOT NULL
Level int not NULL
CONSTRAINT KEYS PRIMARY KEY (NR, SNR, SSNR)
);
INSERT INTO info
VALUES (123, 1, 1, 1), (123, 1, 2, 2),
(123, 1, 3, 2), (123, 2, 1, 1),
(123, 2, 2, 2), (123, 2, 3, 2),
(124, 1, 1, 1), (124, 1, 2, 2),
(124, 1, 3, 2), (125, 1, 1, 1),
(125, 1, 2, 2), (125, 1, 3, 2),
(125, 1, 4, 3), (125, 1, 5, 3),
(220, 1, 1, 1), (220, 1, 2, 2),
(223, 1, 1, 1), (223, 1, 2, 2),
(224, 1, 1, 1), (224, 1, 2, 2),
(224, 1, 3, 2), (225, 1, 1, 1),
(225, 1, 2, 2), (300, 1, 1, 1),
(300, 1, 2, 2), (300, 2, 1, 1),
(300, 2, 2, 2), (540, 1, 1, 1),
(541, 1, 1, 1);
Step #1:
SELECT *
FROM con1
INNER JOIN con2 ON con1.NR = con2.NR
WHERE con1.flag = 1
Step #2:
SELECT ref.*
FROM ref
INNER JOIN step1 ON ref.ID = step1.ID
Step #3:
SELECT *
FROM step2
INNER JOIN info ON step2.NR = info.NR
WHERE info.Level = 1
I tried some different ways but always get too much resulting rows
the result should look like this:
ID
NR
Level
SNR
SSNR
1234
223
1
1
1
1234
224
1
1
1
1234
225
1
1
1
1235
123
1
1
1
1235
123
1
2
1
1235
124
1
1
1
1236
540
1
1
1
1236
541
1
1
1
It should be all entries from info with Level=1
excluding:
all NR that do not occur in the intersection of con1 and con2
all NR that con1 lists with flag = 0
but including:
all excluded NR that run with the same ID (according to ref) as any NR not excluded prior
the result has the same columns as info with on NR matching IDs from ref

You can do this easily with Common Table Expressions:
with step1 As (
Select *
From con1
Inner Join con2 On con1.NR = con2.NR
Where con1.flag = 1
), step2 As (
Select ref.*
From ref
Inner Join step1 On ref.ID = step1.ID
)
Select *
From step2
Inner Join info On step2.NR = info.NR
Where info.Level = 1

Related

How to create a columns based on other columns SQL Server 2012

I have 2 tables #Claims and #ClaimsActivity:
Query:
declare #Claims table (ClaimID int)
insert into #Claims
values (6070), (6080)
declare #ClaimsActivity table
(
Activityid int,
ClaimID int,
Activity int,
ActivityDate datetime,
ClaimStatus int
)
insert into #ClaimsActivity
values (1, 6070, 0, '2017-11-05 20:23:16.640', 0),
(3, 6070, 6, '2017-11-06 13:50:28.203', 0),
(4, 6070, 9, '2017-11-07 13:39:28.410', 0),
(5, 6070, 10, '2017-11-07 13:40:49.980', 0),
(7, 6070, 8, '2017-11-07 15:46:18.367', 1),
(8, 6070, 8, '2017-11-07 16:50:49.543', 1),
(9, 6070, 9, '2017-11-07 16:50:54.733', 0),
(10, 6070, 4, '2017-11-07 16:55:22.135', 0),
(11, 6070, 6, '2017-11-08 18:32:15.101', 0),
(12, 6080, 0, '2017-11-12 11:15:17.199', 0),
(13, 6080, 8, '2017-11-13 09:12:23.203', 1)
select *
from #Claims
select *
from #ClaimsActivity
order by ActivityDate
I need to add 2 columns based on data in #ClaimsActivity: IsReopened and DateReopened
The logic is:
If the last ClaimStatus (based on ActivityDate) = 1 then IsReopened = 0
But if the last ClaimStatus = 0 then it need to go and check whether one of the Activity is = 9 (Claim Reopened)
and if one of the Activity = 9 then IsReopened should = 1 and DateReopened should be the last date when it was reopened
I brought column StatusOfClaim, but I also need IsReopened and DateReopened
select
Claimid,
isnull((select top 1
case when al.ClaimStatus = 1
then 'Closed'
else 'Open'
end
from
#ClaimsActivity al
where
C.ClaimID = al.ClaimID
order by
al.ActivityDate desc), 'Open') as 'Status of Claim',
NULL as 'isReopen',
NULL as 'DateReopened'
from
#Claims c
Desired output should be like this:
There are many different ways you can accomplish this, but here is an example using CROSS APPLY and OUTER APPLY:
SELECT
ClaimID,
CASE WHEN tmp.IsOpen = 1 THEN 'Open' ELSE 'Closed' END AS 'Status of Claim',
CASE WHEN tmp.IsOpen = 1 AND lastReopen.Activityid IS NOT NULL THEN 1 ELSE 0 END AS 'isReopen',
lastReopen.ActivityDate AS 'DateReopened'
FROM #Claims c
CROSS APPLY (
SELECT ISNULL((
SELECT TOP 1 CASE WHEN al.ClaimStatus = 1 THEN 0 ELSE 1 END
FROM #ClaimsActivity al
WHERE c.ClaimID = al.ClaimID
ORDER BY al.ActivityDate DESC
), 1) AS IsOpen
) tmp
OUTER APPLY (
SELECT TOP 1
al.Activityid,
al.ActivityDate
FROM #ClaimsActivity al
WHERE c.ClaimID = al.ClaimID AND al.Activity = 9
ORDER BY al.ActivityDate DESC
) lastReopen
The CROSS APPLY is just used to produce a column that tells us whether a claim is open or closed, and we can reuse this throughout the rest of the query.
The OUTER APPLY is used to grab to the last "reopen" activity for each claim, of which you want the date.
I can't attest to the performance of this query, but this should at least give you the correct results.

Update rows based on previous value of same column. (MSSQL2008)

I have a table with one column:
ColA Rownumb
1 1
1 2
1 3
2 4
1 5
1 6
1 7
2 8
2 9
2 10
2 11
2 12
2 13
2 14
3 15
2 16
2 17
2 18
3 19
3 20
3 21
3 22
3 23
3 24
On row 4 the value of ColA changes for the first time. From row 8 it has changed permanently in the sense that following rows also have value 2. I want to update rows 5, 6 and 7 so that value 1 becomes 2. The same logic goes for rows 16, 17 and 18. In that case I want to update ColA from 2 to 3.
So how do I updated the rows as specified above?
Thanks.
Since you area using SQL-Server-2008 you can do this with recursive common table expression:
DECLARE #DataSource TABLE
(
[ColA] INT
,[Rownumb] INT
);
INSERT INTO #DataSource ([ColA], [Rownumb])
VALUES (1, 1), (1, 2), (1, 3), (2, 4), (1, 5), (1, 6), (1, 7), (2, 8), (2, 9), (2, 10), (2, 11), (2, 12), (2, 13), (2, 14), (3, 15), (2, 16), (2, 17), (2, 18), (3, 19), (3, 20), (3, 21), (3, 22), (3, 23), (3, 24);
WITH DataSourceRecursive AS
(
SELECT [ColA]
,[Rownumb]
FROM #DataSource
WHERE [Rownumb] = 1
UNION ALL
SELECT CASE WHEN DS1.[ColA] < DSR.[ColA] THEN DSR.[ColA] ELSE DS1.[ColA] END
,DS1.[Rownumb]
FROM #DataSource DS1
INNER JOIN DataSourceRecursive DSR
ON DS1.[Rownumb] = DSR.[RowNumb] + 1
)
SELECT *
FROM DataSourceRecursive;

Count and divide number on rows

i have the following dataset
1, Nike
2, Adidas
3, oasis
4, reebok
5, puma
6, airjordan
for each 2 rows affect them to A,and so on
A, 1, Nike
A, 2, Adidas
B, 3, oasis
B, 4, reebok
C, 5, puma
C, 6, airjordan
I believe this is what you looking for:
You will need to use DENSE_RANK()
Sample Data:
DECLARE #Shoes TABLE ( ShoesId INT, Brand VARCHAR(10))
INSERT INTO #Shoes
VALUES
(1, 'Nike'),
(2, 'Adidas' ),
(3, 'oasis'),
(4, 'reebok'),
(5, 'puma'),
(6, 'airjordan')
Query:
SELECT CHAR(ASCII('A') + DENSE_RANK() OVER ( ORDER BY (ShoesId%2) + ShoesId -1) - 1),
*
FROM #Shoes
Results:

Select query using variable not running in mssql

Select query is not working when use variable in MSSQL2014
My Schema is :-
CREATE TABLE product
(idproduct int, name varchar(50), description varchar(50), tax decimal(18,0))
INSERT INTO product
(idproduct, name, description,tax)
VALUES
(1, 'abc', 'This is abc',10),
(2, 'xyz', 'This is xyz',20),
(3, 'pqr', 'This is pqr',15)
CREATE TABLE product_storage
(idstorage int,idproduct int,added datetime, quantity int, price decimal(18,0))
INSERT INTO product_storage
(idstorage,idproduct, added, quantity,price)
VALUES
(1, 1, 2010-01-01,0,10.0),
(2, 1, 2010-01-02,0,11.0),
(3, 1, 2010-01-03,10,12.0),
(4, 2, 2010-01-04,0,12.0),
(5, 2, 2010-01-05,10,11.0),
(6, 2, 2010-01-06,10,13.0),
(7, 3, 2010-01-07,10,14.0),
(8, 3, 2010-01-07,10,16.0),
(9, 3, 2010-01-09,10,13.0)
and i am executing below command:-
declare #price1 varchar(10)
SELECT p.idproduct, p.name, p.tax,
[#price1]=(SELECT top 1 s.price
FROM product_storage s
WHERE s.idproduct=p.idproduct AND s.quantity > 0
ORDER BY s.added ASC),
(#price1 * (1 + tax/100)) AS [price_with_tax]
FROM product p
;
This is not working in MSSQL, Please Help me out.
for detail check http://sqlfiddle.com/#!6/91ec2/296
And My query is working in MYSQL
Check for detail :- http://sqlfiddle.com/#!9/a71b8/1
Try this query
SELECT
p.idproduct
, p.name
, p.tax
, (t1.price * (1 + tax/100)) AS [price_with_tax]
FROM product p
inner join
(
SELECT ROW_NUMBER() over (PARTITION by s.idproduct order by s.added ASC) as linha, s.idproduct, s.price
FROM product_storage s
WHERE s.quantity > 0
) as t1
on t1.idproduct = p.idproduct and t1.linha = 1
Try it like this:
Explanantion: You cannot use a variable "on the fly", but you can do row-by-row calculation in an APPLY...
SELECT p.idproduct, p.name, p.tax,
Price.price1,
(price1 * (1 + tax/100)) AS [price_with_tax]
FROM product p
CROSS APPLY (SELECT top 1 s.price
FROM product_storage s
WHERE s.idproduct=p.idproduct AND s.quantity > 0
ORDER BY s.added ASC) AS Price(price1)
;
EDIT: Your Fiddle uses a bad literal date format, try this:
INSERT INTO product_storage
(idstorage,idproduct, added, quantity,price)
VALUES
(1, 1, '20100101',0,10.0),
(2, 1, '20100102',0,11.0),
(3, 1, '20100103',10,12.0),
(4, 2, '20100104',0,12.0),
(5, 2, '20100105',10,11.0),
(6, 2, '20100106',10,13.0),
(7, 3, '20100107',10,14.0),
(8, 3, '20100108',10,16.0),
(9, 3, '20100109',10,13.0)
Here is the correct schema for SQL Server and query runs perfect as Shnugo Replied.
VALUES
(1, 1, convert(datetime,'2010-01-01'),0,10.0),
(2, 1, convert(datetime,'2010-01-02'),0,11.0),
(3, 1, convert(datetime,'2010-01-03'),10,12.0),
(4, 2, convert(datetime,'2010-01-04'),0,12.0),
(5, 2, convert(datetime,'2010-01-05'),10,11.0),
(6, 2, convert(datetime,'2010-01-06'),10,13.0),
(7, 3, convert(datetime,'2010-01-07'),10,14.0),
(8, 3, convert(datetime,'2010-01-07'),10,16.0),
(9, 3, convert(datetime,'2010-01-09'),10,13.0)

SQL Server stored procedure return table with count of uniques per user

I have found a little here and a little there but nothing that really covers the question that I have so here goes. I have ordered a book from amazon but it won't be here for another week and I really need to this ASAP
I have two tables which contain basically the following.
Table A has the users id number, login name, wins, losses, ties
Table B has the User id number, when the game ended, game state
What I want is to create a stored procedure that will return the top 10 for wins for the last week.
Loginname | total wins, last 7 days | all wins | all losses | all ties
Name1 | 10 | 40 | 8 | 6
Name2 | 9 | 96 | 76 | 19
etc....
What I have so far is:
SELECT A.login,
A.draws_count,
A.losses_count,
A.wins_count
FROM [TableB] AS B
INNER JOIN
[TableA] AS A
ON B.won_by_id = A.id
WHERE B.win_defined_time > (GETDATE() - 7)
AND B.state = 'OVER';
From there I have no clue how to return the table that I need. Any assistance would be greatly appreciated. (also keep in mind that the 'total wins for the last 7 days' field does not exist in either table.)
Assuming a schema and sample data such as the following:
CREATE TABLE [dbo].[Competitors]
(
[id] INT NOT NULL,
[login_name] VARCHAR (50) NOT NULL,
[wins] INT NOT NULL,
[losses] INT NOT NULL,
[ties] INT NOT NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[Events]
(
[id] INT NOT NULL,
[Competitorid] VARCHAR (50) NOT NULL,
[EventDateTime] DATETIME NOT NULL,
[winner] BIT NOT NULL,
[EventStatus] VARCHAR (50) NOT NULL
) ON [PRIMARY]
INSERT INTO Competitors (id, login_name, wins, losses, ties)
VALUES (1, 'Player 1', 40, 8, 6),
(2, 'Player 2', 96, 76, 19),
(3, 'Player 3', 1, 0, 0)
INSERT INTO Events (id, Competitorid, EventDateTime, winner, EventStatus)
VALUES (1, 1, '2013-01-25 01:05:25.000', 1, 'OVER'),
(2, 1, '2013-01-26 01:05:25.000', 1, 'OVER'),
(3, 1, '2013-01-27 14:05:25.000', 1, 'OVER'),
(4, 1, '2013-01-28 01:05:25.000', 1, 'OVER'),
(5, 1, '2013-01-29 15:05:25.000', 1, 'OVER'),
(6, 1, '2013-01-30 01:05:25.000', 1, 'OVER'),
(7, 1, '2013-01-31 22:05:25.000', 1, 'OVER'),
(8, 1, '2013-02-01 01:05:25.000', 1, 'OVER'),
(9, 1, '2013-02-02 21:05:25.000', 1, 'OVER'),
(10, 1, '2013-01-02 11:05:25.000', 0, 'INPROGRESS'),
(11, 1, '2013-01-30 01:05:25.000', 1, 'OVER'),
(12, 2, '2013-01-25 11:05:25.000', 1, 'OVER'),
(13, 2, '2013-01-26 01:05:25.000', 1, 'OVER'),
(14, 2, '2013-01-27 11:25:25.000', 1, 'OVER'),
(15, 2, '2013-01-28 01:05:25.000', 1, 'OVER'),
(16, 2, '2013-01-29 11:45:25.000', 1, 'OVER'),
(17, 2, '2013-01-30 01:45:25.000', 1, 'OVER'),
(18, 2, '2013-01-31 12:15:25.000', 1, 'OVER'),
(19, 2, '2013-02-01 01:05:25.000', 1, 'OVER'),
(20, 2, '2013-02-02 22:25:25.000', 1, 'OVER'),
(21, 2, '2013-02-02 15:05:25.000', 0, 'INPROGRESS'),
(22, 2, '2013-01-25 01:05:25.000', 1, 'OVER'),
(23, 1, '2013-01-30 01:05:25.000', 0, 'OVER'),
(24, 2, '2013-01-30 01:05:25.000', 0, 'OVER'),
(25, 3, '2012-01-30 01:05:25.000', 1, 'OVER')
You can return the names and wins data for the ten people with the most wins in the last 7 days using the following query:
SELECT TOP 10 login_name,
recent_wins,
wins AS 'All Wins',
losses AS 'All losses',
ties AS 'All Ties'
FROM Competitors
INNER JOIN
(SELECT COUNT(*) AS recent_wins,
Competitorid
FROM events
WHERE winner = 1
AND eventdatetime BETWEEN GetDate() - 7 AND GetDate()
AND EventStatus = 'OVER'
GROUP BY Competitorid) AS recent_event_winners
ON Competitors.ID = recent_event_winners.Competitorid;
ORDER BY recent_wins DESC
This query works by joining the data in the Competitors table together with a subquery on the data in the events table that is calaculating the number of recent wins and then taking the top 10 results. For users with a win in the last seven days, the subquery returns the count of the number of wins the user has had for events that are over during that time period.
Note: users without any wins during the time period will not be returned by either query so the results may have fewer than 10 results.
A SQL Fiddle with the above sql creation scripts and query can be found at http://sqlfiddle.com/#!3/0ebc8/2

Resources