Update table in sql query - sql-server

I am struggling with the following (apparently) easy task; my table (call it table1) look like this:
id | date | value
------------------
1 | 01 | 100
1 | 02 | 103
1 | 04 | 105
1 | 05 | 90
1 | 06 | 95
1 | 09 | 0
2 | 02 | 110
2 | 03 | 98
2 | 04 | 97
2 | 07 | 71
2 | 08 | 84
2 | 10 | 0
------------------
I would like to replace the two 0s with, respectively 95 and 84 (i.e. previous values in time). Any solution? I have been spending a looot of time on this (sorry but I am quite new to SQL)

Try this:
update table1 as a
set a.value=(select b.value
from table1 as b
where b.date<=a.date order by b.date desc limit 1)
where a.value=0;
Change to this
Make a new replica of table1 as table2 (same structure & same data in table1 and table2):
SET SQL_SAFE_UPDATES = 0;
update table1
set value=(select value
from table2
where table2.date<table1.date order by table2.date desc limit 1)
where table1.value=0;

Building up on nacho's query:
MySQL's update is a bit flawed. First: it doesn't accept an alias for the updated table. Second: It complains when you access the same table you want to update in the query. The latter can easily be solved by replacing from table1 b with from (select * from table1) b.
nacho's statement also missed to have the subquery refer to the same ID. And he mistakenly included the record itself (b.date <= instead of b.date <).
update table1
set value =
(
select b.value
from (select * from table1) b
where b.id = table1.id and b.date < table1.date
order by b.date desc limit 1
)
where value = 0;
And here is a test: http://rextester.com/YQV55035
UPDATE: You obviously tagged the wrong DBMS. Here is the same query for SQL Server:
update table1
set value =
(
select top(1) b.value
from table1 b
where b.id = table1.id and b.date < table1.date
order by b.date desc
)
where value = 0;

Related

t sql Group By clause not having intended effect

I am having some trouble with what I believe is a group by clause. I am trying to display a distinct CompanyID with the earliest InstallDate
Here is my code:
SELECT
Pa.PARTY_ID
,MIN(SM.[INSTALLDATE]) INSTALLDATE
,SM.[STOPDATE]
FROM FORMDESC FD
INNER JOIN STATEINFO SI
ON FD.FORMDESCID = SI.FORMDESCID
INNER JOIN COMPANY C
ON FD.COMPANYID = C.COMPANYID
INNER JOIN PARTY Pa
ON C.COMPANYFULLNAME = Pa.FULL_NM
INNER JOIN STATEMARKET SM
ON SI.STATEINFOID = SM.STATEINFOID
WHERE ENTIREFORMNUMBER = 'ABC123'
GROUP BY PARTY_ID, INSTALLDATE, STOPDATE
My current output is:
CompanyID | INSTALLDATE | STOPDATE
-------------------------------------------
60 | NULL | NULL
61 | 2015-09-26 00:00:00 | NULL
62 | NULL | NULL
62 | 2014-09-29 00:00:00 | NULL
62 | 2016-04-15 00:00:00 | NULL
The output I am seeking is:
CompanyID | INSTALLDATE | STOPDATE
----------------------------------------
60 | NULL | NULL
61 | 2015-09-26 00:00:00 | NULL
62 | 2014-09-29 00:00:00 | NULL
A left join on the SM table will not help me here either. If I pull any of the values from my group by clause, I get an error.
Is this a case where I should break this into a couple of selects instead?
While James Z's answer would indeed work; it was pointed out to me that my group by contained INSTALLDATE which caused my issue.
You probably need something like this:
select * from (
SELECT
Pa.PARTY_ID
,SM.[INSTALLDATE]
,SM.[STOPDATE]
,row_number() over (partition by Pa.PARTY_ID order by SM.[INSTALLDATE] desc) as RN
FROM FORMDESC FD
INNER JOIN STATEINFO SI
ON FD.FORMDESCID = SI.FORMDESCID
INNER JOIN COMPANY C
ON FD.COMPANYID = C.COMPANYID
INNER JOIN PARTY Pa
ON C.COMPANYFULLNAME = Pa.FULL_NM
INNER JOIN STATEMARKET SM
ON SI.STATEINFOID = SM.STATEINFOID
WHERE ENTIREFORMNUMBER = 'ABC123'
) X
where RN = 1
This will number the rows separately for each party_id, and then show the earliest one of them. This way you can get other data from the same row where the minimum value exists.

SP to update 3rd table using data in first 2 tables

For e.g. I have below table1 and table3. The 'Counts' field in table2 should be updated based on valuess field in table1 and table3. i.e. 23 appears 4 times in table1 and table3 and 45 appears once. Table2 should be updated with that count.
table1
Id | Data | Valuess
1 | rfsd | 23
2 | fghf | 45
3 | rhhh | 23
table3
Id | Data | Valuess
1 | rfsd | 23
2 | tfgy | 23
table2
Id | Fields | Counts
1 | 23 | 4
2 | 45 | 1
I am using the below stored procedure to achieve this.
WITH t13 AS (
SELECT Id, Data, Valuess FROM Table1 UNION ALL SELECT Id, Data, Valuess FROM Table3),
cte AS (SELECT Valuess,COUNT(*) AS Count2 FROM t13 GROUP BY Valuess)
UPDATE t2
SET t2.Counts = cte.Count2
FROM Table2 t2 JOIN cte ON t2.Fields = cte.Valuess;
QUESTION
Now instead of above table data, i have below table data....
table1
Id | Data | Valuess
1 | rfsd | 004561
2 | fghf | 0045614
3 | rhhh | adcwyx
table3
Id | Data | Valuess
1 | rfsd | 0045614
2 | tfgy | 004561
table2
Id | Fields | Counts
1 | 0045614 | 4
2 | adcwyxv | 1
So here we have alphanumeric data in valuess field of table1 and table3. Also we have data like '004561' and '0045614'
I want to clip off the 7th element of the field and compare it with clipping off 7th element in the table 3. i.e. 004561, 004561 and adcwyx will be taken from table1. 004561 and 004561 will be taken from table3 and compared with 004561 and adcwyx of table2 ( we need to clip off 7th element in table2 first) and then compare.
The final result should be as shown in table2.
SUBSTRING should do it.
WITH t13 AS (
SELECT Id, Data, SUBSTRING(Valuess,1,6) AS [Values]
FROM Table1
UNION ALL
SELECT Id, Data, SUBSTRING(Valuess,1,6) AS [Values]
FROM Table3
)
, cte AS (
SELECT [Values],COUNT(*) AS Count2
FROM t13 GROUP BY [Values]
)
UPDATE t2
SET t2.Counts = cte.Count2
FROM Table2 t2 JOIN cte ON SUBSTRING(t2.Fields,1,6) = cte.[Values];

SQL Server: Find records with closest Date to CurrentDate based on conditions

I'm using SQL Server 2012 and I'm attempting to create a VIEW that would return records based on these conditions:
Query needs to retrieve most applicable record based on date
For dates that are within an inner Date Range, the closest record to CurrentDate will be returned
For dates that are outside an inner Date Range, the closest record to CurrentDate will be returned
Sample tables in the database:
Person table:
pId | Name
----------------------
01 | Person 1
02 | Person 2
----------------------
PersonDate table:
dId | pId | StartDate | EndDate
---------------------------------------------------
A1 | 01 | 2014-01-08 | 2018-01-08
A2 | 01 | 2016-11-23 | 2016-12-01
A3 | 01 | 2016-12-03 | 2016-12-08
A4 | 02 | 2016-10-10 | 2016-12-31
A5 | 02 | 2016-12-01 | 2016-12-05
If I run this query and the CurrentDate is 2016-11-28:
select p.name, d.startdate, d.enddate
from Person p, PersonDate d
where p.pId = d.pId
and d.StartDate = (select max(sl.StartDate)
from PersonDate sl
where d.pId = s1.pId)
The records that are returned are:
name | startdate | enddate
-------------------------------------------
Person 1 | 2016-12-03 | 2016-12-08 --> PersonDate Table row A3
Person 2 | 2016-12-01 | 2016-12-05 --> PersonDate Table row A5
-------------------------------------------
Both returned records are incorrect based on the conditions I'm trying to get back. I understand why I'm getting the returned records, and it is due to using the Max() function within my subquery, but I don't know how to write the query/subquery.
The correct records that I want to be return are (CurrentDate being 2016-11-28):
name | startdate | enddate
-------------------------------------------
Person 1 | 2016-11-23 | 2016-12-01
Person 2 | 2016-10-10 | 2016-12-31
-------------------------------------------
PersonDate table row A2, since this inner Date Range falls closest to CurrentDate (condition #2)
PersonDate table row A4, since the inner Date Range (A5) hasn't come yet (condition #3)
When CurrentDate is 2016-12-02:
name | startdate | enddate
---------------------------------------------
Person 1 | 2014-01-08 | 2018-01-08
Person 2 | 2016-12-01 | 2016-12-05
---------------------------------------------
PersonDate table row A1, since CurrentDate is outside both row A2 and A3 inner Date Ranges
PersonDate table row A5, since CurrentDate is inside a Date Range
How can I write a VIEW that would return records based on the conditions above?
create table #temp(did varchar(10),pid int,startdate datetime,enddate datetime)
insert into #temp values('A1',01,'2014-01-08','2018-01-08')
insert into #temp values('A2',01, '2016-11-23' , '2016-12-01' )
insert into #temp values('A3',01, '2016-12-03' , '2016-12-08' )
insert into #temp values('A4',02, '2016-10-10' , '2016-12-31' )
insert into #temp values('A5',02, '2016-12-01' , '2016-12-05' )
select b.pid,b.startdate,b.enddate
from
(
select ROW_NUMBER()over(partition by pid order by id desc) as SID , a.*
from
(
select
ROW_NUMBER()over(partition by pid order by startdate,enddate desc) as ID
, * from #temp
--to identify whether it is inner or outer
--1 means outer
--2 means inner
)a
where '2016-12-02' between startdate and enddate
--to find date lies in outer or inner range and select the required
)b
where b.SID=1

Concat records SQL Server

I have this query and i can't make it to concatanete the second column.
SELECT
Container.UIDaughterPlateId AS UIDaughterPlateId,
AllLastOperationInfo.OperationShortLabel AS lab
FROM
((InSite.UIDaughterPlate AS Container
INNER JOIN
InSite.UIDaughterPlateInfo AS UIDaughterPlateInfo ON (Container.UIDaughterPlateInfoId = UIDaughterPlateInfo.UIDaughterPlateInfoId ))
LEFT OUTER JOIN
(SELECT
UIOperationInfo.UIOperationInfoId as OperationInfoId,
UIOperationInfo.ParentId as DaughterPlateInfoId,
UIOperationInfo.Status as Status,
Operation.ShortLabel as OperationShortLabel,
UIOperationInfo.IsLast
FROM
UIOperationInfo
INNER JOIN
Operation ON Operation.OperationId = UIOperationInfo.UIOperationId
WHERE
UIOperationInfo.IsLast = 1 and Status = 'A RĂ©aliser') AllLastOperationInfo ON (UIDaughterPlateInfo.UIDaughterPlateInfoId = AllLastOperationInfo.DaughterPlateInfoId ))
ORDER BY
Container.UIDaughterPlateName DESC
The current results are
-------------------------
| UIDaughterPlateId | Lab |
|-------------------------|
| 42 | MD |
| 42 | MC |
| 47 | MC |
| 67 | MA |
| 67 | MB |
| 67 | MC |
-------------------------
And I want to have these results
-------------------------------
| UIDaughterPlateId | Lab |
|-------------------------------|
| 42 | MC MD |
| 47 | MC |
| 67 | MA MB MC |
-------------------------------
I've tried several examples that I found in other post but without success.
Can someone help me?
Thank you
You can try the following code:
-- Create demo data
CREATE TABLE #temp(UIDaughterPlateId int, Lab nvarchar(5))
INSERT INTO #temp(UIDaughterPlateId, Lab)
VALUES (42,N'MD'),(42, N'MC'),(47, N'MC'),(67, N'MA'),(67, N'MB'),(67, N'MC')
-- Your part:
SELECT DISTINCT t.UIDaughterPlateId, LEFT(dat.Lab,LEN(dat.Lab)-1) as Lab
FROM #temp AS t
OUTER APPLY (
SELECT s.Lab+N', '
FROM #temp as s
WHERE s.UIDaughterPlateId = t.UIDaughterPlateId
FOR XML PATH(N'')
) as dat(Lab)
-- Cleanup
DROP TABLE #temp
On the given input:
UIDaughterPlateId Lab
----------------- -----
42 MD
42 MC
47 MC
67 MA
67 MB
67 MC
This is the result of the query:
UIDaughterPlateId Lab
----------------- ----------
42 MD, MC
47 MC
67 MA, MB, MC
If you want to adapt it to your table structure just use a CTE for this.
WITH data AS(
-- your code from your question
SELECT
Container.UIDaughterPlateId AS UIDaughterPlateId,
AllLastOperationInfo.OperationShortLabel AS lab
FROM
((InSite.UIDaughterPlate AS Container
INNER JOIN
InSite.UIDaughterPlateInfo AS UIDaughterPlateInfo ON (Container.UIDaughterPlateInfoId = UIDaughterPlateInfo.UIDaughterPlateInfoId ))
LEFT OUTER JOIN
(SELECT
UIOperationInfo.UIOperationInfoId as OperationInfoId,
UIOperationInfo.ParentId as DaughterPlateInfoId,
UIOperationInfo.Status as Status,
Operation.ShortLabel as OperationShortLabel,
UIOperationInfo.IsLast
FROM
UIOperationInfo
INNER JOIN
Operation ON Operation.OperationId = UIOperationInfo.UIOperationId
WHERE
UIOperationInfo.IsLast = 1 and Status = 'A RĂ©aliser') AllLastOperationInfo ON (UIDaughterPlateInfo.UIDaughterPlateInfoId = AllLastOperationInfo.DaughterPlateInfoId ))
ORDER BY
Container.UIDaughterPlateName DESC
)
SELECT DISTINCT t.UIDaughterPlateId, LEFT(dat.Lab,LEN(dat.Lab)-1) as Lab
FROM data AS t
OUTER APPLY (
SELECT s.Lab+N', '
FROM data as s
WHERE s.UIDaughterPlateId = t.UIDaughterPlateId
FOR XML PATH(N'')
) as dat(Lab)
Create a view A using your current results, and execute
SELECT UIDaughterPlateId, replace(group_concat(lab),',',' ') AS lab FROM A GROUP BY UIDaughterPlateId

How to count values from rows and display the result in columns

please help me
Oracle | Status| other columnns |
41 | A |
52 | W |
41 | A |
52 | W |
41 | W |
__________________
I need a resulting query that shows the count of Status in every Oracle like this:
Oracle | Total(A) | Total(W) |
41 | 2 | 1 |
52 | 0 | 2 |
Try this
with CTE AS
( select oracle,status from TableName)
select * from CTE
Pivot
(count(status) for status in ([A],[W]) ) as pvt
Try this:
select oracle, count(distinct status)
from your_table
group by oracle
You won't have the exact same result but you will have all the data you need to build that table.
You could also try some windows functions.
There are at least 2 ways to get that data:
1.
SELECT t1.oracle, ISNULL(Total_A, 0) As [Total (A)], ISNULL(Total_W,0) As [Total (W)]
FROM
(
SELECT oracle, count(status) As Total_A
FROM TableName
WHERE status = 'A'
GROUP BY oracle
) t1 INNER JOIN
(
SELECT oracle, count(status) As Total_W
FROM TableName
WHERE status = 'W'
GROUP BY oracle
) t2 ON(t1.oracle = t2.oracle)
This will give you the table you asked for, however, I will not recommend it as it is a terrible mess.
2.
SELECT oracle, status, COUNT(status)
FROM TableName
GROUP BY oracle, status
This will give you a table that you can then arrange in code to look like the table you requested in very little effort. Also, it is much cleaner and will be easy to handle a new status if introduced to the system.

Resources