Update table in Sql - sql

Table tblProductStock:
ID Name Qyt
1 X 50
2 Y 40
3 Z 30
Table tblStockMinus:
Id Name Qty
1 X 10
1 X 20
2 Y 30
3 Z 20
I want to update tblProductStock so that it will have:
ID Name Qyt
1 X 20
2 Y 10
3 Z 10
I have tried to use the following SQL request, but it didn't work correctly:
UPDATE ProductStock_Show
SET Quantity = ProductStock_Show.Quantity - ProductStock_Show_Minus.Quantity
FROM ProductStock_Show JOIN ProductStock_Show_Minus
ON ProductStock_Show_Minus.ProductId=ProductStock_Show.ProductId

This will give you required result.
select t1.id, t1.qty-t2.qty as qty from tblProductStock as t1 inner join
(
select id, sum(qty) as qty from tblStockMinus group by id
) as t2 on t1.id=t2.id
You need to update this (but it depends in the RDBMS. This is for MS SQL Server)
Update t
set
t.qty=t3.qty from tblProductStock as t inner join
(
select t1.id, t1.qty-t2.qty as qty from tblProductStock as t1 inner join
(
select id, sum(qty) as qty from tblStockMinus group by id
) as t2 on t1.id=t2.id
) as t3 on t.id=t3.id

DECLARE #Table1 TABLE
( ID int, Name varchar(1), Qyt int)
;
INSERT INTO #Table1
( ID , Name , Qyt )
VALUES
(1, 'X', 50),
(2, 'Y', 40),
(3, 'Z', 30)
;
DECLARE #Table2 TABLE
( Id int, Name varchar(1), Qty int)
;
INSERT INTO #Table2
( Id , Name , Qty )
VALUES
(1, 'X', 10),
(1, 'X', 20),
(2, 'Y', 30),
(3, 'Z', 20)
;
UPDATE #Table1 SET QYT =
t.Qyt - s from (
select
t.id,
t.Name,
t.Qyt ,
SUM(tt.Qty)S
FROM #Table1 t
INNER JOIN #Table2 tt
ON t.Name = tt.Name
GROUP BY t.id,t.Name,t.Qyt)T
SELECT * from #Table1

Related

Search for records that do not contain a specific value

I have a table that contains IDs from two other tables. Those are two integer numbers.
CustomerId SectionId
====================
1 1
1 2
1 3
2 2
2 3
3 1
3 2
3 3
4 2
4 3
What I am looking for is for those records that have the SectionId=1 missing. For the above example I need to retrieve CustomerId 2 and 4.
I cannot do a Select customer ID where SectionId <> 1 because it will bring me all records (1 to 4). I specifically need those that, independently of which SectionId they have, are missing SectionId=1
Thanks.
You need NOT EXISTS:
SELECT DISTINCT t1.CustomerId
FROM tablename t1
WHERE NOT EXISTS (SELECT 1 FROM tablename t2 WHERE t2.CustomerId = t1.CustomerId AND t2.SectionId = 1)
Or, with conditional aggregation:
SELECT CustomerId
FROM tablename
GROUP BY CustomerId
HAVING COUNT(CASE WHEN SectionId = 1 THEN 1 END) = 0
Try this
select distinct id
from Test
where id not in (
select distinct id
from Test
where section = 1
);
check 2 examples
Declare #t Table (CustomerId int, SectionId int)
insert into #t Values
(1, 1),
(1, 2),
(1, 3),
(2, 2),
(2, 3),
(3, 1),
(3, 2),
(3, 3),
(4, 2),
(4, 3)
select DISTINCT CustomerId from #t
where CustomerId not in (
select CustomerId from #t
where SectionId = 1
group by CustomerId
)
SELECT DISTINCT t1.CustomerId
FROM #t t1
WHERE NOT EXISTS (SELECT * FROM #t t2
WHERE t2.CustomerId = t1.CustomerId AND t2.SectionId = 1)

SQL server, how to get a number of distinct items

I am using SQL server,
id 3 | 4 | 5 | 6
items 1 2 3 | 2 3 5| 6 | 1 2 5
-------------------------
# of items 3 | 4 | 5 | 5
so, each id has items (ex, 3 has 3 items - 1,2,3)
and for each item, I'd like to get the number of distinct items accrued.
so, 3 has 3 distinct items - 1, 2, 3
4 has 4 distinct items - 1, 2, 3, 5
5 has 5 distinc items - 1, 2, 3, 5, 6
6 has 5 distinct items - 1, 2, 3, 5, 6
I can do this by running, 1 through 2, 1 though 3, 1 through 5 and 1 through 6 by doing count(distinct items)
But I want to automate this process and get the same results in one run.
The idea is to create a temp table and put an item in it while checking if the item is already in the temp table and print number of distinct items for each id.
CREATE TABLE TEST
(
id int, items int
)
INSERT INTO TEST
VALUES
(3, 1),
(3, 2),
(3, 3),
(4, 2),
(4, 3),
(4, 5),
(5, 6),
(6, 1),
(6, 2),
(6, 5)
SELECT B.id, COUNT(DISTINCT(A.ITEMS)) AS itemCount
FROM TEST A
INNER JOIN TEST B ON A.id <= B.id
GROUP BY B.ID
DROP TABLE TEST
Output:
id itemCount
3 3
4 4
5 5
6 5
Assuming your data in below format:
Declare #table table
(
id int,
items varchar(10)
)
insert into #table values (3, '1 2 3');
insert into #table values (4, '2 3 5');
insert into #table values (5, '6');
insert into #table values (6, '1 2 5');
with cte as
(
Select id, b.Item
from #table a
cross apply [dbo].[Split] (items, ' ') b
)
Select y.id, count(distinct(x.Item)) AS [# of items]
from cte x
join cte y on x.id <= y.id
group by y.id
Use the table valued function [dbo].[Split] from LINK.
You can as the below:
DECLARE #Tbl TABLE (Id VARCHAR(10), Column3 VARCHAR(100), Column4 VARCHAR(100), Column5 VARCHAR(100), Column6 VARCHAR(100))
INSERT #Tbl
VALUES
('items', '1 2 3', '2 3 5', '6', '1 2 5')
;WITH CTE1
AS
(
SELECT T.Id, T.Column3 AS ColumnId, CAST('<X>' + REPLACE(T.Column3,' ','</X><X>') + '</X>' as XML) AS FilterColumn FROM #Tbl T UNION ALL
SELECT T.Id, T.Column4 AS ColumnId, CAST('<X>' + REPLACE(T.Column4,' ','</X><X>') + '</X>' as XML) AS FilterColumn FROM #Tbl T UNION ALL
SELECT T.Id, T.Column5 AS ColumnId, CAST('<X>' + REPLACE(T.Column5,' ','</X><X>') + '</X>' as XML) AS FilterColumn FROM #Tbl T UNION ALL
SELECT T.Id, T.Column6 AS ColumnId, CAST('<X>' + REPLACE(T.Column6,' ','</X><X>') + '</X>' as XML) AS FilterColumn FROM #Tbl T
), CTE2
AS
(
SELECT
A.*,
B.SplitData
FROM
CTE1 A CROSS APPLY
(SELECT fdata.D.value('.','varchar(50)') AS SplitData FROM A.FilterColumn.nodes('X') as fdata(D)) B
)
SELECT
T.Id ,
(SELECT COUNT(DISTINCT C.SplitData) FROM CTE2 C WHERE C.Id = T.Id AND C.ColumnId IN (T.Column3)) Column3OfDistinct,
(SELECT COUNT(DISTINCT C.SplitData) FROM CTE2 C WHERE C.Id = T.Id AND C.ColumnId IN (T.Column3, T.Column4)) Column4OfDistinct,
(SELECT COUNT(DISTINCT C.SplitData) FROM CTE2 C WHERE C.Id = T.Id AND C.ColumnId IN (T.Column3, T.Column4, T.Column5)) Column5OfDistinct,
(SELECT COUNT(DISTINCT C.SplitData) FROM CTE2 C WHERE C.Id = T.Id AND C.ColumnId IN (T.Column3, T.Column4, T.Column5, T.Column6)) Column6OfDistinct
FROM
#Tbl T
Result:
Id Column3OfDistinct Column4OfDistinct Column5OfDistinct Column6OfDistinct
---------- ----------------- ----------------- ----------------- -----------------
items 3 4 5 5
This should help you:
select
id,
count(items)
from table_name
group by id

Is there any way to get TOP N records from table 1 where N based on Table 2

Table1
Rowno name Date
------------------------------------
1 sathish Dec 21
2 kumar Dec 22
3 sathish Dec 21
4 sathish Dec 22
5 sathish Dec 21
5 sathish Dec 22
Table 2
Date NoofTran
-----------------------
Dec22 2
Dec21 1
I want to get the records from table1 based on the table2 nooftran values and randomly.
On dec22nd, the number of transaction is 2 in the table 2, so two records should take it from table 1 on the respective date and it should be random case. So out of 3 records on Dec22 , two should come randomly.
What SQL query should I use?
If you are using SQL Server you can use a cross apply like this
select t1.*
from Table2 as t2
cross apply
(
select top (select T2.nooftran) *
from Table1 as t1
where t2.Date = t1.date
order by newid()
) as t1
Sample
declare #T1 table (rowno int, name varchar(max), [date] date);
declare #T2 table ([date] date, nooftran int);
insert into #T1 values
(1, 'sathish', '2015-01-01'),
(2, 'kumar', '2016-01-01'),
(3, 'sathish', '2015-01-01'),
(4, 'sathish', '2016-01-01'),
(5, 'sathish', '2015-01-01'),
(5, 'sathish', '2016-01-01');
insert into #T2 values ( '2016-01-01', 2), ( '2015-01-01', 1);
select t1.*
from #T2 as t2
cross apply
(
select top (select T2.nooftran) *
from #T1 as t1
where t2.Date = t1.date
order by newid()
) as t1
SELECT rs.RowNo, rs.DATE, rs.NAME
FROM (
SELECT t1.ROWNO, t1.DATE, t1.NAME, Rank() OVER (
PARTITION BY t1.DATE ORDER BY newid()
) AS Rank
FROM table1 t1
) rs
INNER JOIN Table2 T2 ON rs.DATE = t2.DATE
WHERE Rank <= t2.NoofTran

Full Outer Join on Incomplete Data (by id variable)

I have two tables (see example data below). I need to keep all of the ID values in table 1 and merge table 1 with table 2 by sequence. The tricky part is that I also have to retain the field value1 from table 1 and value2 from table 2.
table 1 :
ID sequence value1
-------------------------
p1 1 5
p1 2 10
p2 1 15
p2 2 20
table 2 :
sequence value2
-------------------------
1 10
2 20
3 30
4 40
I need the resulting table to appear like so:
ID sequence value1 value2
----------------------------------
p1 1 5 10
p1 2 10 20
p1 3 - 30
p1 4 - 40
p2 1 15 10
p2 2 20 20
p2 3 - 30
p2 4 - 40
I have tried the following sql code, but it doesn't merge the missing values from from value1 field in table 1 and merge it with the values2 field from table 2
select t1.ID, t2.sequence, t1.value1, t2.value2 from
t2 full outer join t1 on t2.sequence=t1.sequence
Any assistance you can provide is greatly appreciated.
You can try something like this:
select coalesce(t1.[id], t3.[id]),
, t2.[sequence]
, t1.[value]
, t2.[value]
from [tbl2] t2
left join [tbl1] t1 on t1.[sequence] = t2.[sequence]
left join (select distinct [id] from [tbl1]) t3 on t1.[id] is null
SQLFiddle
One way with CROSS JOIN and OUTER APPLY:
DECLARE #t1 TABLE(ID CHAR(2), S INT, V1 INT)
DECLARE #t2 TABLE(S INT, V2 INT)
INSERT INTO #t1 VALUES
('p1', 1, 5),
('p1', 2, 10),
('p2', 1, 15),
('p2', 2, 20)
INSERT INTO #t2 VALUES
(1, 10),
(2, 20),
(3, 30),
(4, 40)
SELECT c.ID, t2.S, ca.V1, t2.V2 FROM #t2 t2
CROSS JOIN (SELECT DISTINCT ID FROM #t1) c
OUTER APPLY(SELECT * FROM #t1 t1 WHERE c.ID = t1.ID AND t1.S = t2.S) ca
ORDER BY c.ID, t2.S
Output:
ID S V1 V2
p1 1 5 10
p1 2 10 20
p1 3 NULL 30
p1 4 NULL 40
p2 1 15 10
p2 2 20 20
p2 3 NULL 30
p2 4 NULL 40
Given this schema:
create table #table_1
(
ID varchar(8) not null ,
sequence int not null ,
value int not null ,
primary key clustered ( ID , sequence ) ,
unique nonclustered ( sequence , ID ) ,
)
create table #table_2
(
sequence int not null ,
value int not null ,
primary key clustered ( sequence ) ,
)
go
insert #table_1 values ( 'p1' , 1 , 5 )
insert #table_1 values ( 'p1' , 2 , 5 )
insert #table_1 values ( 'p2' , 1 , 15 )
insert #table_1 values ( 'p2' , 2 , 20 )
insert #table_2 values ( 1 , 10 )
insert #table_2 values ( 2 , 20 )
insert #table_2 values ( 3 , 30 )
insert #table_2 values ( 4 , 40 )
go
This should get you what you want:
select ID = map.ID ,
sequence = map.sequence ,
value1 = t1.value ,
value2 = t2.value
from ( select distinct
t1.ID ,
t2.sequence
from #table_1 t1
cross join #table_2 t2
) map
left join #table_1 t1 on t1.ID = map.ID
and t1.sequence = map.sequence
join #table_2 t2 on t2.sequence = map.sequence
order by map.ID ,
map.sequence
go
Producing:
ID sequence value1 value2
== ======== ====== ======
p1 1 5 10
p1 2 5 20
p1 3 - 30
p1 4 - 40
p2 1 15 10
p2 2 20 20
p2 3 - 30
p2 4 - 40

Need a tweak in SQL Server

Tbl 1
ID Name Email
1 A a#b.c
2 B b#c.d
Tbl2
ID Related_ID Value Name
1 1 Z Name1
2 1 Y Name2
3 2 X Name1
4 2 W Name2
5 2 G Name3
I can write a query to show
ID Name Email Value1
1 A a#b.c Z
1 A a#b.c Y
How can I write it so it will become like
ID Name Email Value1 Value2
1 A a#b.c Z Y
2 B b#c.d X W
Here is an example to get what you want using dynamic sql.
Note that the CTE test and the temporary table #tmp2 should map to your original tables.
create table #tmp (ID int, Related_ID int, Value nvarchar(50), Name nvarchar(50), rn int)
delete #tmp
create table #tmp2 (ID int, Name nvarchar(50), Email nvarchar(50))
delete #tmp2
;with test(ID, Related_ID, Value, Name)
as
(
select 1, 1, 'Z', 'Name1'
union all
select 2, 1, 'Y', 'Name2'
union all
select 3, 2, 'X', 'Name1'
union all
select 4, 2, 'W', 'Name2'
union all
select 5, 2, 'G', 'Name3'
)
insert into #tmp
select *, row_number() OVER (partition by Related_ID order by ID) as rn
from test
insert into #tmp2
select 1, 'A', 'a#b.c'
union all
select 2, 'B', 'b#c.d'
declare #d nvarchar(MAX)
,#e nvarchar(MAX)
SET #d = 'select a.ID, a.Name, a.Email '
SET #e = ',min(case b.rn when >rn< then Value else null end) as [Value>rn<]'
select #d = #d + (
select t from(
select distinct replace(#e,'>rn<', b.rn) as [text()]
from #tmp b
for xml path('')) c(t)
)
set #d = #d + '
from #tmp2 a
join #tmp b
on a.ID = b.Related_ID
group by a.ID, a.Name, a.Email'
exec sp_executesql #d
drop table #tmp
drop table #tmp2
declare #t1 table(id int, name varchar(20), email varchar(32))
declare #t2 table(id int, related_id int, value varchar(10), name varchar(10))
insert #t1 values(1,'A', 'a#b.c')
insert #t1 values(2,'B', 'b#c.d')
insert #t2 values(1, 1, 'Z', 'Name1')
insert #t2 values(2, 1, 'Y', 'Name2')
insert #t2 values(3, 2, 'X', 'Name1')
insert #t2 values(4, 2, 'W', 'Name2')
insert #t2 values(5, 2, 'G', 'Name3')
;with a as
(
select value, related_id, ROW_NUMBER() over(PARTITION BY related_id order by value desc) rn
from #t2
), b as
(
select value, related_id, rn from a where rn in (1,2)
)
select t5.ID, t5.Name, t5.Email, t3.value Value1, t4.value Value2
from #t1 t5
join b t3
on t3.related_id = t5.id and t3.rn = 1
join b t4
on t4.related_id = t5.id and t4.rn = 2
Result:
ID Name Email Value1 Value2
------ ------ ---------- -------- ----------
1 A a#b.c Z Y
2 B b#c.d X W
It can be done using PIVOT Statement.
Here are a couple of links you can have a look at.
http://blog.sqlauthority.com/2008/06/07/sql-server-pivot-and-unpivot-table-examples/