SQL Table to SQL Table - sql-server

I have a database table in the following format (populated via .net function, empties are blank, not NULL):
A B C D
Spoons ID
38483
Date Amt Value Type
1/1/2017 2 12 Plastic
1/2/2017 4 30 Silver
1/3/2017 1 9 Wood
How can I write a stored procedure that will result in the following table?
Col1 Col2 Col3 Col4 Col5
----------------------------------------------------
Spoons 38483 1/1/2017 2 Plastic
Spoons 38483 1/2/2017 4 Silver
Spoons 38483 1/3/2017 1 Wood
Note: I am using SQL Server 2016

SELECT LEAD ( [A], 1 ) OVER (ORDER BY [ID] asc) as Col1 FROM Table1 --- (Note I added an ID clmn)
SELECT Top 1 LEAD ( [B], 2 ) OVER (ORDER BY [ID] asc) as Col2 FROM Table1
SELECT ROW_NUMBER() OVER (ORDER BY [ID] asc) AS RowNumber, * FROM Table1 WHERE RowNumber BETWEEN x AND y
Then insert all that into a final table... Simple question = simple answer. I'm just relatively new to sql so it was difficult to figure out on my own.

Related

Custom order by in SQL Server

Below is the select statement
select *
from #final
order by
case
when [Col1] in (select top 10 [Col1] from #take order by [Col2] desc)
then 0
else 2
end
My above select statement returns the result as below
Col1 Col2
--------------------------------------
App 86748
AppService 832
BK 21227
Cap 160272
Fukusima 1634
McBaa 1727
Others 6718
However, I would like to get this result instead:
Col1 Col2
--------------------------------------
Cap 160272
App 86748
BK 21227
McBaa 1727
Fukusima 1634
AppService 832
Others 6718
How to achieve this? Thanks.
You just differenced between the two types, but inside that type 0, there is no second order method. Just add then Col1 as second order, descending.
select * from #final
order by
case when [Col1] in (select top 10 [Col1] from #take order by [Col2] desc) then 0
else 2
end, [Col2] desc
With the below table structure
CREATE TABLE final
([col1] varchar(10), [col2] int)
;
INSERT INTO final
([col1], [col2])
VALUES
('App', 86748),
('AppService', 832),
('BK', 21227),
('Cap', 160272),
('Fukusima', 1634),
('McBaa', 1727),
('Others', 6718)
;
The below query will give exact results
select * from final
order by
case when [Col1] in (select top 6 [Col1] from final order by [Col1] asc) then Col2
end desc,
[Col1] asc
col1 | col2
-----------------------
Cap | 160272
App | 86748
BK | 21227
McBaa | 1727
Fukusima | 1634
AppService | 832
Others | 6718

How to get previous record if current record does not exist in table

my table like this
Id Date type quantity
1 29/04/2019 APPLE 2
2 29/04/2019 Banana 15
3 29/04/2019 Mango 100
4 29/04/2019 Grapes 50
5 29/04/2019 Fish 80
6 30/04/2019 APPLE 4
7 30/04/2019 Grapes 100
8 30/04/2019 Fish 90
9 01/05/2019 APPLE 6
10 01/05/2019 Banana 30
11 01/05/2019 Grapes 150
12 01/05/2019 Fish 100
13 02/05/2019 Mango 200
14 02/05/2019 Grapes 200
15 02/05/2019 Fish 110
16 03/05/2019 APPLE 8
17 03/05/2019 Banana 45
18 03/05/2019 Mango 300
19 04/05/2019 APPLE 10
20 04/05/2019 Grapes 300
21 04/05/2019 Fish 120
22 05/05/2019 APPLE 12
23 05/05/2019 Fish 130
i miss some inputs every day,But i need to fill the gaps with previous row of the same "Type" on 30/04/2019 i missed "Banana & Mango" bu i need like
Id Date type quantity
1 29/04/2019 APPLE 2
2 29/04/2019 Banana 15
3 29/04/2019 Mango 100
4 29/04/2019 Grapes 50
5 29/04/2019 Fish 80
6 30/04/2019 APPLE 4
7 30/04/2019 Grapes 100
8 30/04/2019 Fish 90
9 30/04/2019 Banana 15
10 30/04/2019 Mango 100
actually last two rows are null but it should updated same on 29/04/2019
I think the easiets way might be this:
DECLARE #PDate DATE = SELECT TOP 1 Date FROM YourTable ORDER BY Date ASC --Previous Date
DECLARE #NDate DATE = SELECT TOP 1 Date FROM YourTable WHERE DATE>#PDate --Next Date
WHILE (#NDate IS NOT NULL)
BEGIN
WITH X AS
(
SELECT T1.Date AS Date1, T1.Type AS Type1, T1.Quantity AS Q1
T2.Date AS Date2, T2.Type AS Type2, T2.Quantity AS Q2
FROM YourTable T1
LEFT JOIN YourTable T2 ON T1.Type = T2.Type
WHERE T1.Date = #PDate AND T2.Date = #NDate
)
INSERT INTO YourTable (Date,Type,Quantity)
SELECT #NDate,Type1,Q1
WHERE X.Type2 IS NULL
SET #PDate = #NDate
SET #NDate = NULL -- If next result wasnt found this stays null for while condition
SET #NDate = SELECT TOP 1 Date FROM YourTable WHERE Date>#PDate
END
I think this is the way that may work and I wish so
( if there is any syntax or ... mistakes its because I didnt have SSMS installed to test. Sorry)
try this :
declare #date date
and for initiate #date you can use select #date=max(date) from table1 or pass static value set #date='02/01/2019'
and then find input
select input,max(date) as MaxDate into #temp
from table1
where input not in (select input from table1 where date=#date )
group by input
then :
select t.* from Table1 t join #temp on Table1.input=#temp.Input and Table1.date=#temp.MaxDate
OK, after the goal posts are settled, this is one method. Note that this solution builds both a Types and Dates dataset. Really the Types dataset should already exist somewhere in your database, and you should create a Calendar Table if you're going to be doing this type of work often.
Any way, I've left comments in the code for you. I've assumed you're using SQL Server 2012+, as 2008 is literally about to run out of support.
CREATE TABLE dbo.MyTable (ID int IDENTITY(1,1),
[date] date,
[type] varchar(10),
Quantity int);
INSERT INTO dbo.MyTable
SELECT CONVERT(date,[date],103),
RTRIM([Type]),
Quantity
FROM (VALUES('29/04/2019','APPLE ',2),
('29/04/2019','Banana',15),
('29/04/2019','Mango ',100),
('29/04/2019','Grapes',50),
('29/04/2019','Fish ',80),
('30/04/2019','APPLE ',4),
('30/04/2019','Grapes',100),
('30/04/2019','Fish ',90),
('01/05/2019','APPLE ',6),
('01/05/2019','Banana',30),
('01/05/2019','Grapes',150),
('01/05/2019','Fish ',100),
('02/05/2019','Mango ',200),
('02/05/2019','Grapes',200),
('02/05/2019','Fish ',110),
('03/05/2019','APPLE ',8),
('03/05/2019','Banana',45),
('03/05/2019','Mango ',300),
('04/05/2019','APPLE ',10),
('04/05/2019','Grapes',300),
('04/05/2019','Fish ',120),
('05/05/2019','APPLE ',12),
('05/05/2019','Fish ',130)) V([date],[Type],Quantity);
GO
--SELECT *
--FROM dbo.MyTable;
GO
--Create a calendar table
WITH N AS (
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1, N N2, N N3), --1000 days shuld be enough
Dates AS(
SELECT DATEADD(DAY, T.I, MIN(MT.[date])) AS [Date]
FROM Tally T
CROSS JOIN dbo.MyTable MT
GROUP BY T.I
HAVING DATEADD(DAY, T.I, MIN(MT.[date])) <= MAX([Date])),
--Get Types
Types AS (
SELECT DISTINCT [Type]
FROM dbo.MyTable MT),
--Create islands
Grps AS(
SELECT MT.ID,
D.[Date],
T.[Type],
MT.Quantity,
COUNT(MT.Quantity) OVER (PARTITION BY T.[Type] ORDER BY D.[date]
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
FROM Dates D
CROSS JOIN Types T
LEFT JOIN dbo.MyTable MT ON D.[Date] = MT.[date]
AND T.[type] = MT.[type])
SELECT G.ID AS ID,
ROW_NUMBER() OVER (ORDER BY G.[Date], G.[Type]) AS RN,
G.[Date],
G.[Type],
MAX(G.Quantity) OVER (PARTITION BY G.[Type], G.Grp) AS Quantity
FROM Grps G
ORDER BY G.[Date],
G.[Type];
GO
DROP TABLE dbo.MyTable;
db<>fiddle
I think using cursor is a good option to insert your missing entries in the table. By cursor you will be able to check date wise missing types and insert them with the previous quantity.
You can also use this following script to find the missing records in your table. To create the script I consider the table name = 'add_missing_records'
SELECT AA.date AS [Date],
AA.type AS [Type],
BB.quantity AS [Original Quantity] ,
CASE
WHEN BB.quantity IS NULL THEN
(
SELECT quantity
FROM add_missing_records C
WHERE C.date = (
SELECT MAX([date])
FROM add_missing_records B
WHERE B.date < AA.date
AND B.type = AA.type
)
AND C.type = AA.type
)
ELSE BB.quantity
END AS [New Quantuty]
FROM (
SELECT date,type
FROM (
SELECT DISTINCT 'A' AS common,date
FROM add_missing_records
)A
FULL JOIN (
SELECT DISTINCT 'A' as common, type
FROM add_missing_records
)B
ON a.common = b.common
) AA
LEFT JOIN add_missing_records BB
ON AA.date = BB.date
AND AA.type = BB.type
WHERE BB.quantity IS NULL
ORDER BY 1,2

Pivot Table in SQL without using Aggegate Function

I am using SQL server 2012 . I have table like
col1 col2 col3
1 abc AA
2 xyz BB
3 def CC
I want to convert this table into
col1 col2 col3_AA col3_BB col3_CC
1 abc AA
2 xyz BB
3 def CC
please edit table format. I am not able to do
The conditional aggregation might help you
select col1, col2,
max(case when col3 = 'AA' then col3 end) col3_AA,
max(case when col3 = 'BB' then col3 end) col3_BB,
max(case when col3 = 'CC' then col3 end) col3_CC
from table
group by col1, col2
order by col1
Try This
1. Static PIVOT query.
For example, if the column "ITEM_HEAD_ID" values can only be like 1, 2 and 3, then this is what you need. According to your given data, you can use the following query:
SELECT *, (ISNULL([1], 0 ) + ISNULL([2], 0) + ISNULL([3], 0)) AS [Total]
FROM (SELECT [TRXID],
[ITEM_HEAD_ID],
[ITEM_HEAD_AMT]
FROM [Table]) AS t
PIVOT (MAX([ITEM_HEAD_AMT])
FOR [ITEM_HEAD_ID] IN ([1], [2], [3])) AS p;
Note: [Table] is the name of your table.
The result:
TRXID 1 2 3 Total
6 100.00 100.00 300.00 500.00
7 100.00 100.00 300.00 500.00

value comparison on sql server 2008

There is a table of 5 columns :
col1,col2,col3,col4,monthName
Something like:
col1 | col2 | col3 | col4 | monthName
----------------------------------------
4 | 5 | 55 | 8 | January
4 | 4 | 33 | 6 | February
col1 and col2 sum must be same as col4 of the last month. So i can compare it like
select * from table1 where col1+col2=col4 where monthName='February'
but it will compare all the rows wheres i want it to be month specific something like
select *
from table1
where col1+col2 = (select col4 from table1 where monthName='January')
where monthName='February'
How i do this in correct way?
Well, It is something about monthly report.
Perhaps my main problem is getting col4 from the past month(such as january).
I am trying to explain it more clearly:
Get the col1 and col2 of current month(Which is in the monthName column) and do the sum.
Get the col4 cells value from last month. In this case it is February of monthName column.
Compare the col1+col2(Current month) to col4 (Last month in monthName).
In my first example , the row number 2 is true because 4+4=8 which is getting matched with col4 value(8) of January. If col1 and col2 sum of current month match with last month's col4 data then users are good.
I can get col1 and col2 very easily:
select sum(col1+col2) as currentTotal from table1 where monthName='February'
But how i get the col4 value from last month and store it somewhere then compare to currentTotal? Every month there will be 15 rows inserted and will be compared to last month.
Not sure if this time i explained a little better!
The month naming is dubious, but with the information we have, the following should do the trick:
-- Creating a table variable as a sample for your query.
DECLARE #T TABLE (col1 INT, col2 INT, col3 INT, col4 INT, monthName VARCHAR(25))
INSERT INTO #T VALUES (4,4,55,9,'January'),(5,4,3,6,'February'), (3,3,3,6,'March')
-- Update the references to your actual table in this query.
;WITH CTE AS (SELECT *
, DATEPART(MM,monthName+' 01 2014') Mnum
FROM #T)
SELECT CA.*
FROM CTE C
CROSS APPLY
(SELECT col1, col2, col3, col4, monthName
FROM CTE B
WHERE B.Mnum-1 = C.Mnum AND (B.col1+B.col2 = C.col4)) CA
ORDER BY Mnum
What it does, is it assigns a number for the monthname, then uses that set in order of month numbers, and with CROSS APPLY selects only rows where the sum of col1 and 2 amount to the col4 of previous month number.
You can try something like the pseudo code below
select *
from table1 t1
join
(
select monthName, SUM(col1+col2-col4) as isZero
group by monthName
) as t2
on t2.monthName = t1.monthName
where t2.isZero != 0

Update to get check_order

I have a table with values,
col1 col2 col3
1 0 ABA
1 0 ABB
1 0 ABC
2 0 BBA
2 0 BBB
2 0 BBC
I am trying to update the table to see the number of repetition of col1, in this case col1 has repeated 3 times so each update to col2 incremented by 1.
Required output after the update table
col1 col2 col3
1 1 ABA
1 2 ABB
1 3 ABC
2 1 BBA
2 2 BBB
2 3 BBC
A simple row_number() -ing should work
;with TMP as (
select *, row_number() over (partition by col1 order by col3) as RowNum
from tbl
)
update TMP set col2=RowNum
Where
tbl: is your table name
partition by col1: resets the row numbering for each col1 group
order by col3: is the basis for numbering within a col1 group
Assuming you are intending col3 to be in non-descending order, this should do it:
UPDATE MyTable
SET col2=(SELECT COUNT(*)
FROM MyTable AS T2
WHERE T2.col1=T1.col1 AND T2.col3<=T1.col3)
FROM MyTable AS T1
You will get duplicates in col2, if there are duplicates in col3 for a particular col1 value.
In case you are interested, here is a pretty verbose (and more expensive execution wise) solution using a ranking function. It has the same issue (i.e., the count gets repeated) for duplicates in col1/col3, as the previous solution:
UPDATE MyTable
SET col2=(
-- In the following query, DISTINCT merges rank dups caused by col3 dups
-- SELECT TOP(1) MyRank would also work.
SELECT DISTINCT MyRank
FROM (
SELECT col3,
DENSE_RANK() OVER (PARTITION BY col1 ORDER BY col3) AS MyRank
FROM MyTable
WHERE col1=UpdatedTable.col1
) As RankTable
WHERE RankTable.col3=UpdatedTable.col3)
FROM MyTable AS UpdatedTable

Resources