Can i declare TOP to pull the value from another table - sql-server

I am looking to gather the TOP diff from the inventory table, where the newcount <> quantity.
Basically, if my inventory count was different than it should have been, I want to search my remaining inventory for the TOP # of missing parts. This brings me back an instock id to ensure that I am removing the oldest parts first.
I could have 900 of these, so I am looking for a sql command that returns the results from partsremainingfifo based on the diff and partnumber in inventory.
select
PartNumber,
Quantity,
NewCount,
diff
from Inventory
where NewCount <> Quantity
+------------+----------+----------+------+
| PartNumber | Quantity | NewCount | diff |
+------------+----------+----------+------+
| 2871451 | 1 | 0 | 1 |
| 4932615 | 6 | 1 | 5 |
+------------+----------+----------+------+
select top 1
id, PartNumber,
PartDescription,
Quantity,
TotalPrice,
Brand,
Location,
Account
from PARTSREMAININGFIFO
where PartNumber = '2871451'
+------+------------+-------------------+----------+------------+---------+----------+----------+
| id | PartNumber | PartDescription | Quantity | TotalPrice | Brand | Location | Account |
+------+------------+-------------------+----------+------------+---------+----------+----------+
| 9183 | 2871451 | AFM DEVICE GASKET | 1 | 19.815225 | CUMMINS | A1 | 6015-Z |
+------+------------+-------------------+----------+------------+---------+----------+----------+
select top 5
id,
PartNumber,
PartDescription,
Quantity,
TotalPrice,
Brand,
Location,
Account
from PARTSREMAININGFIFO
where PartNumber = '4932615'
+------+------------+-----------------+----------+------------+---------+----------+---------+
| id | PartNumber | PartDescription | Quantity | TotalPrice | Brand | Location | Account |
+------+------------+-----------------+----------+------------+---------+----------+---------+
| 3264 | 4932615 | GASKET | 1 | 2.907144 | CUMMINS | A1 | 6015-Z |
| 9780 | 4932615 | GASKET | 1 | 5.053475 | CUMMINS | A1 | 6015-Z |
| 9781 | 4932615 | GASKET | 1 | 5.053475 | CUMMINS | A1 | 6015-Z |
| 9782 | 4932615 | GASKET | 1 | 5.053475 | CUMMINS | A1 | 6015-Z |
| 9783 | 4932615 | GASKET | 1 | 5.053475 | CUMMINS | A1 | 6015-Z |
+------+------------+-----------------+----------+------------+---------+----------+---------+

I understand what you want now, and I think you'll need a cursor. One important note, you must specify an order by when you use TOP unless you don't care what rows come back. Read this article.
Here is how you'd implement this:
--create some sample data that you gave
declare #inventory table ( PartNumber int,
Quantity int,
NewCount int,
diff int)
insert into #inventory
values
(2871451,1,0,1),
(4932615,6,1,5)
declare #PARTSREMAININGFIFO table ( id int,
PartNumber int,
PartDescription varchar(64),
Quantity int,
TotalPrice decimal (8,6),
brand varchar(64),
Location varchar(16),
Account varchar(64))
insert into #PARTSREMAININGFIFO
values
(9183,2871451,'AFM DEVICE GASKET',1,19.815225,'CUMMINS','A1','6015-Z'),
(9183,2871451,'AFM DEVICE GASKET',1,19.815225,'CUMMINS','A2','6015-Z'), --notice the extra (2nd) row here for part 2871451
(9183,2871451,'AFM DEVICE GASKET',1,19.815225,'CUMMINS','A3','6015-Z'), --notice the extra (3nd) row here for part 2871451
(3264,4932615,'GASKET',1,2.907144,'CUMMINS','A1','6015-Z'),
(9780,4932615,'GASKET',1,5.053475,'CUMMINS','A1','6015-Z'),
(9781,4932615,'GASKET',1,5.053475,'CUMMINS','A1','6015-Z'),
(9782,4932615,'GASKET',1,5.053475,'CUMMINS','A1','6015-Z'),
(9783,4932615,'GASKET',1,5.053475,'CUMMINS','A1','6015-Z'),
(9783,4932615,'GASKET',1,5.053475,'CUMMINS','A6','6015-Z') --notice the 6th (extra) row here for part 4932615
--staging table for your results
declare #tempResults table ( id int,
PartNumber int,
PartDescription varchar(64),
Quantity int,
TotalPrice decimal (8,6),
brand varchar(64),
Location varchar(16),
Account varchar(64))
declare cur cursor local fast_forward for
select distinct
PartNumber,
diff
from (select
PartNumber,
Quantity,
NewCount,
diff
from #inventory
where NewCount <> Quantity) x
declare #partNumber int
declare #diff int
open cur
fetch next from cur into #partNumber, #diff
while ##FETCH_STATUS = 0
begin
insert into #tempResults
select top (#diff)
id,
PartNumber,
PartDescription,
Quantity,
TotalPrice,
Brand,
Location,
Account
from #PARTSREMAININGFIFO
where PartNumber = #partNumber
order by Quantity --note you need to specify WHAT you want to order by
fetch next from cur into #partNumber, #diff
end
select *
from #tempResults
order by PartNumber
close cur
deallocate cur

Related

How to make autoincrement value for each customer SQL Query

I want to increment InvoiceNumber for every Customer in format "customer/invoicenumber" and make it as a trigger (every time when I add some data, It should add InvoiceNumber.
CustomerID | Price | InvoiceNumber |
1 | 100 | 1/1 |
1 | 200 | 1/2 |
1 | 250 | 1/3 |
2 | 400 | 2/1 |
2 | 100 | 2/2 |
3 | 20 | 3/1 |
4 | 10 | 4/1 |
5 | 1 | 5/1 |
During inserting customer information , you need to insert column 'InvoiceNumber' as null. Then below trigger will update Invoicenumber with new number like 1/2 ...etc
CREATE TRIGGER trig1 ON triggertest
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #CustomerID INT;
DECLARE #MaxID INT;
SELECT #CustomerID = INSERTED.CustomerID FROM INSERTED;
SELECT #MaxID=(select ISNULL(rn,0) from
(select top 1 CustomerID, ROW_NUMBER() OVER(order by CustomerID) as rn from [triggertest] where CustomerID=#CustomerID
order by rn desc) t)
UPDATE triggertest SET InvoiceNumber=CAST(#CustomerID as nvarchar)+'/'+CAST(#MaxID as nvarchar) WHERE CustomerID=#CustomerID and InvoiceNumber is null;
END

How to find the sum of prior amounts for an year including the current amount

I need to get the sum of current with Previous amount of that specific year for the 2nd entry.
Input_table
+-----------+----------+-------------+-----------+----------+
| ID | Name | Date1 |Date 2 |amount |
+-----------+----------+-------------+-----------+----------+
| 10000000 | ABC | 11/2/2017 |**11/2/2018** |2504 |
| 10000000 | ABC | 12/20/2017 |**11/2/2018** |-2174 |
| 10000000 | ABC | 10/05/2018 |10/05/2019 |1234 |
| 10000000 | ABC | 10/06/2019 |10/06/2020 |3456 |
+-----------+----------+-------------+-----------+----------+
Here's the desired output:
+-----------+----------+-------------+-----------+----------+
| ID | Name | Date1 |Date 2 |amount |
+-----------+----------+-------------+-----------+----------+
| 10000000 | ABC | 11/2/2017 |**11/2/2018** |2504 |
| 10000000 | ABC | 12/20/2017 |**11/2/2018** |329 |
| 10000000 | ABC | 10/05/2018 |10/05/2019 |1234 |
| 10000000 | ABC | 10/06/2019 |10/06/2020 |3456 |
+-----------+----------+-------------+-----------+----------+
Record 3 amount - 1234 (1234+0(no records in that year)) as date 2 is different
Record 4 amount - 3456 (3456+0(no records in that year)) as date 2 is different
I'm Looking for sum of current,previous amount value for a record if date 2 of both records are same. Say if we have 3 records with same date 2 value. then first record should have its actual amount value , 2 nd record should have first record amount + 2 record amount and 3 record would have 1st record amount +2 nd record amount+3rd record amount.
I've made some considerable assumptions here. Mainly, that you want to see if the current record's "Date2" value exists somewhere in "Date1" for the previous year (e.g. Date2: 11/02/2018 is looking if Date1: 11/02/2017 exists) and that the ID and Name columns have some sort of relevance in filtering the data.
Here's what I worked with in SSMS:
-- Create sample data.
DECLARE #Data TABLE (
ID VARCHAR(10), [Name] VARCHAR(3), Date1 DATE, Date2 DATE, Amount DECIMAL(18,2)
);
INSERT INTO #Data ( ID, [Name], Date1, Date2, Amount ) VALUES
( '10000000', 'ABC', '11/2/2017', '11/2/2018', 2504),
( '10000000', 'ABC', '12/20/2017', '11/2/2018', -2174),
( '10000000', 'ABC', '10/05/2018', '10/05/2019', 1234),
( '10000000', 'ABC', '10/06/2019', '10/06/2020', 3456);
-- Query sample data
SELECT
MyData.ID, MyData.[Name], MyData.Date1, MyData.Date2, MyData.Amount
, ISNULL( LastYear.Amount, 0 ) AS PreviousYear
, ( MyData.Amount + ISNULL( LastYear.Amount, 0 ) ) AS NewAmount
FROM #Data AS MyData
OUTER APPLY (
SELECT
SubData.Amount AS Amount
FROM #Data AS SubData
WHERE
SubData.ID = MyData.ID
AND SubData.[Name] = MyData.[Name]
AND SubData.Date1 = DATEADD( yy, -1, MyData.Date2 )
AND SubData.Date1 <> MyData.Date1 -- A weak attempt to exclude the current MyData record. Really needs a unique id.
) AS LastYear
ORDER BY
MyData.Date2;
-- Returns
+----------+------+------------+------------+----------+--------------+-----------+
| ID | Name | Date1 | Date2 | Amount | PreviousYear | NewAmount |
+----------+------+------------+------------+----------+--------------+-----------+
| 10000000 | ABC | 2017-11-02 | 2018-11-02 | 2504.00 | 0.00 | 2504.00 |
| 10000000 | ABC | 2017-12-20 | 2018-11-02 | -2174.00 | 2504.00 | 330.00 |
| 10000000 | ABC | 2018-10-05 | 2019-10-05 | 1234.00 | 0.00 | 1234.00 |
| 10000000 | ABC | 2019-10-06 | 2020-10-06 | 3456.00 | 0.00 | 3456.00 |
+----------+------+------------+------------+----------+--------------+-----------+
Ideally, the queried table has a PK that can be used to exclude the current record from being included (note the weak attempt to use Date1).
The same example using a PK (unique id):
DECLARE #Data TABLE (
ID VARCHAR(10), [Name] VARCHAR(3), Date1 DATE, Date2 DATE, Amount DECIMAL(18,2), pk_PrimaryKey INT IDENTITY(1,1) PRIMARY KEY
);
INSERT INTO #Data ( ID, [Name], Date1, Date2, Amount ) VALUES
( '10000000', 'ABC', '11/2/2017', '11/2/2018', 2504),
( '10000000', 'ABC', '12/20/2017', '11/2/2018', -2174),
( '10000000', 'ABC', '10/05/2018', '10/05/2019', 1234),
( '10000000', 'ABC', '10/06/2019', '10/06/2020', 3456);
SELECT
MyData.ID, MyData.[Name], MyData.Date1, MyData.Date2, MyData.Amount
, ISNULL( LastYear.Amount, 0 ) AS PreviousYear
, ( MyData.Amount + ISNULL( LastYear.Amount, 0 ) ) AS NewAmount
FROM #Data AS MyData
OUTER APPLY (
SELECT
SubData.Amount AS Amount
FROM #Data AS SubData
WHERE
SubData.ID = MyData.ID
AND SubData.[Name] = MyData.[Name]
AND SubData.Date1 = DATEADD( yy, -1, MyData.Date2 )
AND SubData.pk_PrimaryKey <> MyData.pk_PrimaryKey
) AS LastYear
ORDER BY
MyData.Date1;
Anyway, this is my best guess based on what little information I had to go on. Hopefully this can get you moving in the right direction.

Find records of nearest date SQL

I have a table dbo.X with DateTime column lastUpdated and a code product column CodeProd which may have hundreds of records, with CodeProd duplicated because the table is used as "stock history"
My Stored Procedure has parameter #Date, I want to get all CodeProd nearest to that date so for example if I have:
+----------+--------------+--------+
| CODEPROD | lastUpdated | STATUS |
+----------+--------------+--------+
| 10 | 2-1-2019 | C1 |
| 10 | 1-1-2019 | C2 |
| 10 | 31-12-2019 | C1 |
| 11 | 31-12-2018 | C1 |
| 11 | 30-12-2018 | C1 |
| 12 | 30-8-2018 | C3 |
+----------+--------------+--------+
and #Date= '1-1-2019'
I wanna get:
+----+--------------+------+
| 10 | 1-1-2019 | C2 |
| 11 | 31-12-2018 | C1 |
| 12 | 30-8-2018 | C3 |
+----+--------------+------+
How to find it?
You can use TOP(1) WITH TIES to get one row with nearest date for each CODEPROD which should be less than provided date.
Try like following code.
SELECT TOP(1) WITH TIES *
FROM [YourTableName]
WHERE lastupdated <= #date
ORDER BY Row_number()
OVER (
partition BY [CODEPROD]
ORDER BY lastupdated DESC);
You can use apply :
select distinct t.CODEPROD, t1.lastUpdated, t1.STATUS
from table t cross apply
( select top (1) t1.*
from table t1
where t1.CODEPROD = t.CODEPROD and t1.lastUpdated <= #date
order by t1.lastUpdated desc
) t1;

Generating unique identifiers as a set based query

I am moving a bunch of code over from entirely cursor based to set based and generating this has been doing my head in. We create a 6 character shortcode (unique) for each company inserted into the database and I (want) to achieve this outside of a cursor.
Example of where I am at so far:
CREATE TABLE #customers (name VARCHAR(50), shortname VARCHAR(10))
INSERT INTO #customers VALUES
('Michael Smith', 'Michae')
,('Michael Douglas', 'Mich_1')
,('Michael Yang', 'Mich_2')
CREATE TABLE #newcustomers (name VARCHAR(50), shortname VARCHAR(10) NULL)
INSERT INTO #newcustomers (name) VALUES
('Michael Black')
,('Michael White')
SELECT * FROM #customers
SELECT * FROM #newcustomers
DECLARE #shortname VARCHAR(10)
DECLARE #iteration INT = 0
WHILE EXISTS(SELECT shortname FROM #customers WHERE shortname = #shortname)
BEGIN
SELECT #shortname = LEFT(name, 6) FROM #newcustomers
UPDATE #newcustomers SET shortname = #shortname
SET #shortname = LEFT(#shortname, 4) + '_' + #iteration
SET #iteration = #iteration + 1
END
Hopefully the example is sufficient in identifying where I am trying to get to, any suggestions or examples would be very helpful. My example does not work.
Try this
Your table as mock-up
CREATE TABLE #customers (ID INT IDENTITY, name VARCHAR(50), shortname VARCHAR(10))
INSERT INTO #customers VALUES
('Michael Smith', 'Michae')
,('Michael Douglas', 'Mich_1')
,('Michael Yang', 'Mich_3')
,('Testman', 'Testma')
,('Testman1', 'Test_1');
CREATE TABLE #newcustomers (ID INT IDENTITY,name VARCHAR(50), shortname VARCHAR(10) NULL)
INSERT INTO #newcustomers (name) VALUES
('Michael Black')
,('Michael White')
,('Testman2')
,('Someone new');
--This CTE will combine all existing names
WITH AllNames AS
(
SELECT '1_old' AS datasource,ID,name,shortname FROM #customers
UNION ALL SELECT '2_new',ID,name,shortname FROM #newcustomers
)
--This CTE will use the combined list and calculate the right "index"
,ShortNames AS
(
SELECT c.*
,A.First6
,ROW_NUMBER() OVER(PARTITION BY A.First6 ORDER BY datasource,ID) AS NrTotal
,ROW_NUMBER() OVER(PARTITION BY datasource,A.First6 ORDER BY datasource,ID) AS Nr
,CASE WHEN ISNUMERIC(SUBSTRING(shortname+' ',6,10))=1
THEN CAST(SUBSTRING(shortname+' ',6,10) AS INT) ELSE 0 END AS ExistIndex
FROM AllNames AS c
CROSS APPLY(SELECT LEFT(name + ' ',6)) AS A(First6)
)
--All new with NrTotal=1 get the 6 letters as is, all other get the index
SELECT *
,CASE WHEN datasource='1_old' THEN shortname ELSE
CASE WHEN datasource='2_new' AND NrTotal=1 THEN First6
ELSE LEFT(First6,4) + '_' + CAST(Nr + (SELECT ISNULL(MAX(x.ExistIndex),1)
FROM ShortNames AS x
WHERE x.First6=ShortNames.First6) AS VARCHAR(5))
END
END
FROM ShortNames
GO
DROP TABLE #customers;
DROP TABLE #newcustomers;
The result
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| datasource | ID | name | shortname | First6 | NrTotal | Nr | ExistIndex | (Kein Spaltenname) |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old | 1 | Michael Smith | Michae | Michae | 1 | 1 | 0 | Michae |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old | 2 | Michael Douglas | Mich_1 | Michae | 2 | 2 | 1 | Mich_1 |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old | 3 | Michael Yang | Mich_3 | Michae | 3 | 3 | 3 | Mich_3 |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old | 4 | Testman | Testma | Testma | 1 | 1 | 0 | Testma |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old | 5 | Testman1 | Test_1 | Testma | 2 | 2 | 1 | Test_1 |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 2_new | 1 | Michael Black | NULL | Michae | 4 | 1 | 0 | Mich_4 |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 2_new | 2 | Michael White | NULL | Michae | 5 | 2 | 0 | Mich_5 |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 2_new | 4 | Someone new | NULL | Someon | 1 | 1 | 0 | Someon |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 2_new | 3 | Testman2 | NULL | Testma | 3 | 1 | 0 | Test_2 |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
One option is to use a computed column.
A table design along these lines would work:
- Sample table.
DECLARE #Sample TABLE
(
Id INT IDENTITY(1, 1),
FullName VARCHAR(255),
ShortName AS LEFT(FullName, 4) + '_' + CAST(Id AS VARCHAR(255))
)
;
-- Add set containing two companies.
INSERT INTO #Sample
(
FullName
)
VALUES
('ABC LTD'),
('XYZ PLC')
;
Returns
Id FullName ShortName
1 ABC LTD ABC _1
2 XYZ PLC XYZ _1
The Id and ShortName columns will be managed by SQL Server. You only need to add the FullName.
EDIT
Reworked example using table variable, to make it easier to play along.

calculate days with gaps

table:
+-----------+--------------+------------+------------+
| RequestID | RequestStaus | StartDate | EndDate |
+-----------+--------------+------------+------------+
| 1 | pending | 9/1/2015 | 10/2/2015 |
| 1 | in progress | 10/2/2015 | 10/20/2015 |
| 1 | completed | 10/20/2015 | 11/3/2015 |
| 1 | reopened | 11/3/2015 | null |
| 2 | pending | 9/5/2015 | 9/7/2015 |
| 2 | in progress | 9/7/2015 | 9/25/2015 |
| 2 | completed | 9/25/2015 | 10/7/2015 |
| 2 | reopened | 10/10/2015 | 10/16/2015 |
| 2 | completed | 10/16/2015 | null |
+-----------+--------------+------------+------------+
I would like to calculate the days opened but exclude the days between completed and reopened. For example, RequestID 1, the days opened will be (11/3/2015 - 9/1/2015) + (GetDate() - 11/3/2015), for request 2, the total days will be (10/7/2015 - 9/5/2015) + ( 10/16/2015 - 10/10/2015).
The result I want will be something like:
+-----------+-------------------------------+
| RequestID | DaysOpened |
+-----------+-------------------------------+
| 1 | 63 + (getdate() - 11/3/2015) |
| 2 | 38 |
+-----------+-------------------------------+
How do I approach this problem? thank you!
Tested. Works well. :)
Note:
1) I suppose the required result = (FirstCompleteEndDate - PendingStartDate)+(Sum of all the Reopen duration)
2) So I used the self joins. Table b provides the exact completed record which immediately follows the in process record for each RequestID. Table c provides Sum of all the Reopen duration.
--create tbl structure
create table #test (RequestID int, RequestStatus varchar(20), StartDate date, EndDate date)
go
--insert sample data
insert #test
select 1,'pending','09/01/2015','10/2/2015'
union all
select 1,'in progress','10/2/2015','10/20/2015'
union all
select 1,'completed','10/20/2015','11/3/2015'
union all
select 1,'reopened','11/3/2015',null
union all
select 2,'pending','09/05/2015','9/7/2015'
union all
select 2,'in progress','09/07/2015','9/25/2015'
union all
select 2,'completed','9/25/2015','10/7/2015'
union all
select 2,'reopened','10/10/2015','10/16/2015'
union all
select 2, 'completed','10/16/2015','11/12/2015'
union all
select 2,'reopened','11/20/2015',null
select * from #test
--below is solution
select a.RequestID, a.Startdate as [PendingStartDate], b.enddate as [FirstCompleteEndDate], c.startdate as [LatestReopenStartDate],
datediff(day,a.startdate,b.enddate)+c.ReopenDays as [days] from #test a
join (
select *, row_number()over(partition by RequestID,RequestStatus order by StartDate) as rid from #test
) as b
on a.RequestID = b.RequestID
join (
select distinct RequestID, RequestStatus, max(StartDate)over(partition by RequestID,RequestStatus) as StartDate,
Sum(Case when enddate is null then datediff(day,startdate,getdate())
when enddate is not null then datediff(day,startdate,enddate)
end)over(partition by RequestID,RequestStatus) as [ReopenDays]
from #test
where RequestStatus = 'reopened'
) as c
on b.RequestID = c.RequestID
where a.RequestStatus ='pending' and b.RequestStatus = 'completed' and b.rid = 1
Result:

Resources