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
Related
I have this table:
col1
col2
1
2
1
1
2
-2
3
1
3
-1
I only want to have a results of distinct col1 which having only col2 are ALL negative.
Which means I want to have only see col1 = 2
How to do that?
SELECT col1 from table1 t
group by t.col1
having max(t.col2) < 0
you can select just col1 from your table where the max value of col2 is less than 0 after grouping by col1.
Example: http://sqlfiddle.com/#!9/08ed9b/25/0
TSQL -- find records in table with multiples in one column, and at least one specific occurrence of a value in another column
If I have:
ourDB.dbo.ourTable with col1 and col2 and col 3
I want to find occurrences such that
* A value of col1 occurs multiple times
* at least one instance of col2 = 'Val1' at least once.
TSQL -- find specific occurrence in table
So one would start with:
Select col1, col2, col3
FROM ourDB.dbo.ourTable
having count(col1) > 1
WHERE
(col2 = 'Val1')
Group by col1, col2, col3
Order by col1, col2, col3
This would find where col2 always occurs with 'Val1', but how is this generalized to Col2 having 'Val1' at least once ?
You must GROUP BY col1 only and with conditional aggregation you get all the col1 values you need:
SELECT * FROM ourDB.dbo.ourTable
WHERE col1 IN (
SELECT col1
FROM ourDB.dbo.ourTable
GROUP BY col1
HAVING COUNT(*) > 1 AND SUM(CASE WHEN col2 = 'Val1' THEN 1 END) > 0
)
ORDER BY col1, col2, col3
If you want only the rows with col2 = 'Val1':
SELECT * FROM ourDB.dbo.ourTable
WHERE
col2 = 'Val1'
AND
col1 IN (
SELECT col1
FROM ourDB.dbo.ourTable
GROUP BY col1
HAVING COUNT(*) > 1 AND SUM(CASE WHEN col2 = 'Val1' THEN 1 END) > 0
)
ORDER BY col1, col3
Alternate method below, originally from a colleague, I modified it some.
NOTE: Not necessarily better than other (accepted) answer, just different approach.
-- GENERIC_JOIN_WITH_SPECIFIC_COUNTS_Q_v_0.sql
USE [ourDB]
SELECT COUNT( distinct titleid) -- also could use COUNT(*)
from ourTable
WHERE
(
(1 <
(
select count( col1)
from ourTable
GROUP BY col1
HAVING (count(col1 > 1)
-- more than one col1 occurence
)
)
AND
(0 <
(
select count(*) from ourTable
WHERE( col2 = 'Val1' )
-- at least one occurence of col2 having 'Val1'
)
)
)
I have some data like:
ID Col1 Col2
--- ----- -----
5 10 10 <--- Matching
5 11 10
5 15 10
6 22 22 <--- Matching
6 10 22
6 12 22
And I tried a query like:
SELECT ID FROM #Table
GROUP BY ID HAVING MAX(COL1) = MAX(COL2)
But, this only returns id 6, as max for group 5 Col1 is 15 which does not match with Col2 max value 10 for group 5. Is there any way to get all groups 5 & 6 which has matching data 10 & 22 in Col1 & Col2?
Expected Output:
ID
---
5
6
Just showing the ID of matching group.
It is as smiple as this:
DECLARE #tblQuestion AS Table
(
ID int,
col1 int,
col2 int
)
INSERT INTO #tblQuestion VALUES
(5,10,10),
(5,11,10),
(5,15,10),
(6,22,22),
(6,10,22),
(6,12,22);
select distinct ID from #tblQuestion a
where a.col1 = a.col2
TRY THIS:
SELECT DISTINCT ID
FROM table_name
WHERE (col1 - col2) = 0
Try the below query. Maybe it is your requirement, first get same value rows and then get max value from group:
DECLARE #tblQuestion AS Table
(
ID INT,
Col1 INt,
Col2 INT
)
INSERT INTO #tblQuestion VALUES(5,10,10)
INSERT INTO #tblQuestion VALUES(5,10,21)
INSERT INTO #tblQuestion VALUES(5,27,10)
INSERT INTO #tblQuestion VALUES(6,10,12)
INSERT INTO #tblQuestion VALUES(6,15,15)
INSERT INTO #tblQuestion VALUES(6,25,25)
INSERT INTO #tblQuestion VALUES(6,18,10)
;WITH T AS
(
SELECT
*,
ROW_NUMBER() OVER (Partition BY ID order by Col1 Desc) AS PartNo
FROM #tblQuestion
WHERE Col1=Col2
)
SELECT ID,Col1,Col2 FROM T
WHERE PartNo=1
ORDER BY ID, Col1 DESC
Output:
Try this:
SELECT distinct ID FROM table_name
where COL1 = COL2
In my case I tried a different approach, as I needed to use GROUP BY & HAVING clause due to my original query complexity like:
SELECT DISTINCT ID FROM #Table
GROUP BY ID
HAVING MAX(CASE WHEN Col1 = Col2 THEN 1 ELSE 0 END) = 1
Just wanted to share my solution here, in case anyone is interested.
I'm trying to conduct a t-sql which is able to perform some calculation by taking the datetime value of the consecutive row subtract with the datetime value of its previous one.
For example:
Col1 Col2
-------------------------------------------------------------------
row 1: | ENTRY_DOOR_CLOSE | 2/12/2014 16:41:40:4140
row 2: | EXIT_DOOR_CLOSE_ENTRY_DOOR_OPEN | 3/12/2014 16:41:40:4140
row 3: | ENTRY_DOOR_CLOSE | 4/12/2014 16:41:40:4140
row 4: | EXIT_DOOR_CLOSE_ENTRY_DOOR_OPEN | 5/12/2014 16:41:40:4140
--------------------------------------------------------------------
Result:
Col1 Col2
---------------------------------------------------------------------
Row 1: | Diff | Row2.DateTime - Row1.DateTime
Row 2: | Diff | Row4.DateTime - Row3.DateTime
---------------------------------------------------------------------
Can anyone suggest an idea to resolve this?
In SQL Server 2012+, you can use the lead() function:
select 'Diff' as col1,
datediff(second, col2, col2_next) as diff_in_seconds
from (select t.*, lead(col2) over (order by col2) as col2_next
from table t
) t
where col1 = 'ENTRY_DOOR_CLOSE';
This assumes that the values are interleaved, as in the question.
Just figured out using CTE can solve my issue in case i'm not using SQL 2k12
;WITH valuedTable AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY ScxxID, SxxID ORDER BY RecordTime) AS RowID
, ScxxID
, SxxID
, Exxx
, RecordTime
, ProcessName
FROM
database..xxx
WHERE
ProcessName = 'EXIT_DOOR_CLOSE_ENTRY_DOOR_OPEN'
OR
ProcessName = 'ENTRY_DOOR_CLOSE'
)
SELECT
valuedTable.ProcessName
, valuedTable.RecordTime
, nex.ProcessName
, nex.RecordTime
, DATEDIFF(S, valuedTable.RecordTime, nex.RecordTime) DIFF
FROM
valuedTable
INNER JOIN
( valuedTable nex ON nex.RowID = valuedTable.RowID + 1 )
AND
( nex.ProcessName = 'EXIT_DOOR_CLOSE_ENTRY_DOOR_OPEN' )
if you use sql server 2012 - use this one (your table is ordered, but this one is variabile too for non ordered table):
;WITH CTE AS (SELECT ROW_NUMBER() OVER (ORDER BY Col2) AS RN, Col1, Col2
FROM YourTable)
SELECT 'Diff' AS Col1, DATEDIFF(HOUR,a.Col2,x.Col2) AS Col2
FROM CTE a
CROSS APPLY (SELECT TOP 1 Col2 FROM CTE b WHERE Col1 = 'EXIT_DOOR_CLOSE_ENTRY_DOOR_OPEN' AND b.RN > a.RN ORDER BY Col2 ASC) x
WHERE Col1 = 'ENTRY_DOOR_CLOSE'
Hope this will help
--CREATE A TEMPORARY TABLE TO HOLD THE GIVEN DATA
DECLARE #Table AS TABLE
(
ID INT IDENTITY(1,1)
,Col1 VARCHAR(50)
,Col2 DATETIMEOFFSET(0)
)
INSERT INTO #Table (COl1,Col2) VALUES ('ENTRY_DOOR_CLOSE', '2014-12-02'),
('EXIT_DOOR_CLOSE_ENTRY_DOOR_OPEN' , '2014-12-03')
,('ENTRY_DOOR_CLOSE','2014-12-04')
,('EXIT_DOOR_CLOSE_ENTRY_DOOR_OPEN' , '2014-12-05')
--Using common table expression do the following
;WITH CTE AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY ID) AS RowID
,CONVERT(date,Col2) AS DateColumn
FROM #Table
)
SELECT
'DIF' AS Col1
,DATEDIFF(DD,SEcondCTE.DateColumn,FirstCTE.DateColumn)
FROM
CTE FirstCTE
INNER JOIN
CTE SEcondCTE
ON
FirstCTE.RowID = SEcondCTE.RowID + 1
WHERE FirstCTE.RowID % 2 =0
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