Select query using variable not running in mssql - sql-server

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)

Related

combining multiple queries / query optimization

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

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.

How to write a case when statement when there are overlaps in T-SQL

I have a table like this
How can I group it to this
Small is the sum of the count when Count <25; Large is the sum of the count when Count>=25; Total is the sum of all counts.
Try it like this...
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
DROP TABLE #TestData;
CREATE TABLE #TestData (
ID INT NOT NULL PRIMARY KEY,
nCount int NOT NULL
);
INSERT #TestData (ID, nCount) VALUES
(1, 10), (2, 15), (3, 22), (4, 23),
(5, 25), (6, 27), (7, 30);
--=====================================
WITH
cte_Totals AS (
SELECT
Total = SUM(td.nCount),
Small = SUM(CASE WHEN td.nCount < 25 THEN td.nCount ELSE 0 END),
Large = SUM(CASE WHEN td.nCount >= 25 THEN td.nCount ELSE 0 END)
FROM
#TestData td
)
SELECT
x.[Group],
x.[Count]
FROM
cte_Totals t
CROSS APPLY (VALUES (1, 'Total', t.Total), (2, 'Small', t.Small), (3, 'Large', t.Large) ) x (SortBy, [Group],[Count])
ORDER BY
x.SortBy;
Results...
Group Count
----- -----------
Total 152
Small 70
Large 82
HTH,
Jason
The simplest way is to use CASE:
SELECT
SUM(Count) as Total,
SUM(CASE WHEN Count < 25 THEN Count ELSE 0 END) as Small,
SUM(CASE WHEN Count >= 25 THEN Count ELSE 0 END) as Large
FROM table
Late answer (keep the accepted as is), but I did want to introduce a concept which may be more helpful down the line.
I maintain a generic Tier Table. The following is a simplified example, but you can take the aggregation tiers out of the code, and put it in a table... things change, and you can serve multiple masters.
Sample Data
Declare #YourTable table (ID int,[Count] int)
Insert Into #YourTable values
(1, 10), (2, 15), (3, 22), (4, 23), (5, 25), (6, 27), (7, 30)
Declare #Tier table (Tier varchar(50),Seq int,Title varchar(50),R1 int,R2 int)
Insert Into #Tier values
('MyGroup',1,'Total',0,99999)
,('MyGroup',2,'Small',0,25)
,('MyGroup',3,'Large',25,99999)
The Actual Query
Select T.Title
,[Count] = sum(D.[Count])
From #Tier T
Join #YourTable D on (T.Tier='MyGroup' and D.Count >= T.R1 and D.Count<T.R2)
Group By T.Title,T.Seq
Order By T.Seq
Returns
Title Count
Total 152
Small 70
Large 82
EDIT - There are many ways you can construct this
Example
Declare #YourTable table (ID varchar(50),[Count] int)
Insert Into #YourTable values
('Tywin', 10), ('Tywin', 15), ('Tyrion', 22), ('Bran', 23), ('Ned', 25), ('John', 27), ('Robb', 30)
Declare #Tier table (Tier varchar(50),Seq int,Title varchar(50),R1 int,R2 int,C1 varchar(50),C2 varchar(50))
Insert Into #Tier values
('MyGroup',1,'Total' ,null,null,'a','z')
,('MyGroup',2,'Group 1',null,null,'Tywin,Tyrion',null)
,('MyGroup',3,'Group 2',null,null,'Bran,Ned,John,Robb',null)
Select T.Title
,[Count] = sum(D.[Count])
From #Tier T
Join #YourTable D on T.Tier='MyGroup' and (D.ID between C1 and C2 or patindex('%,'+D.ID+',%',','+C1+',')>0)
Group By T.Title,T.Seq
Order By T.Seq
Returns
Title Count
Total 152
Group 1 47
Group 2 105

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:

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