I received this answer to this question MS SQL Server Last User Logged in Multiple Clients with Multiple Users and it works great.
;with cte as
(
select
client, myuser, lastlogin,
row_number() over (partition by client order by lastlogin desc) r#
from
#mytable
)
select *
from cte
where r# = 1
How do I get this joined to a regular Select statement that selects data from other tables also?
For example:
SELECT t1.id, t2.name
FROM table1 t1
JOIN table2 t2 ON (t2.id = t1.id)
WHERE t1.id = 1
There is no restriction, you can just join a result of a cte with other tables. Cte is a subquery, but it makes your code more readable.
;with cte as(
select client,myuser,lastlogin,row_number() over(partition by client order by lastlogin desc) r#
from #mytable
)
SELECT t1.id, t2.name
FROM table1 t1
JOIN table2 t2 ON (t2.id = t1.id)
JOIN cte t3 ON (...)
WHERE t1.id = 1
This is the same as a query with cte.
SELECT t1.id, t2.name
FROM table1 t1
JOIN table2 t2 ON (t2.id = t1.id)
JOIN ( select client,myuser,lastlogin,row_number() over(partition by client order by lastlogin desc) r#
from #mytable) t3 ON (...)
WHERE t1.id = 1
Related
I have 2 tables Table1 and Table2 in which I want to get the total count of duplicate rows:
Expected output:
Query tested:
SELECT
t1.name,
t1.duplicates,
ISNULL(t2.active, 0) AS active,
ISNULL(t3.inactive, 0) AS inactive
FROM
(SELECT
t1.name, COUNT(*) AS duplicates
FROM
(SELECT c.name
FROM table1 c
INNER JOIN table2 as cd on cd.id = c.id)) t1
GROUP BY
name
HAVING
COUNT(*) > 1) t1
LEFT JOIN
(SELECT c.name, COUNT(*) AS active
FROM table1 c
WHERE name IN (SELECT c.name FROM table1 c)
GROUP BY c.name AND status = 'Active'
GROUP BY name) t2 ON t1.name = t2.name
LEFT JOIN
(SELECT c.name, COUNT(*) AS inactive
FROM table1 c
WHERE name IN (SELECT c.name FROM table1 c GROUP BY c.name)
AND status = 'InActive'
GROUP BY name) t3 ON t1.name = t3.name
ORDER BY
name
It is still returning duplicate rows and I'm unable to get the id and creator column
If you would pardon subquery and left join, i'd suggest the following query:
select b.*,
count(creator) as creator_count
from
(select a.mainid,
a.name,
sum(case when a.status = "active"
then 1 else 0 end) as active_count,
sum(case when a.status = "inactive"
then 1 else 0 end) as inactive_count,
count(a.name) as duplicate_count
from table1 as a
group by a.name
having count(a.name) > 1) as b
left join table2 as c
on b.mainid = c.mainid
group by c.mainid
having count(c.creator) > 1
rather than forcing our way to join the two table directly. First, derive the information we can get from the Table1 then join it with the Table2 to get the creator count.
SQL Fiddle: http://sqlfiddle.com/#!9/4daa19e/28
I have this column in my table and I want to get all skipped transactions (which is a varchar)
SA1
SA3
SA50
SA999
I'm trying to get
SA2
SA4 to SA49
SA51 to SA998
EDIT: I've checked the actual data, found out that it's non-trailing zeroes.
I've done this with PHP. Was wondering if is there a way within SQL to do it?
This might sound dumb, but what I'm trying is to plot it like this (this returns null values)
WITH cte (id) AS (
SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM sys.all_columns AS s1
CROSS JOIN sys.all_columns AS s2
),
table1 AS (
SELECT sNumber as id1 FROM Sales WHERE sNumber LIKE '%SI_'
),
table2 AS (
SELECT sNumber as id1 FROM Sales WHERE sNumber LIKE '%SI__'
),
table3 AS (
SELECT sNumber as id1 FROM Sales WHERE sNumber LIKE '%SI___'
)
SELECT
'SA' + RIGHT('' + CAST(t1.id AS VARCHAR(2)), 1) AS id_missing
FROM cte t1
LEFT JOIN table1 t2
ON t1.id = CAST(RIGHT(t2.id1, 1) AS INT)
WHERE
t1.id < (SELECT MAX(CAST(RIGHT(id1, 1) AS INT)) FROM yourTable1) AND
t2.id1 IS NULL
UNION ALL
SELECT
'SA' + RIGHT('' + CAST(t1.id AS VARCHAR(2)), 2) AS id_missing
FROM cte t1
LEFT JOIN table2 t2
ON t1.id = CAST(RIGHT(t2.id2, 2) AS INT)
WHERE
t1.id < (SELECT MAX(CAST(RIGHT(id2, 2) AS INT)) FROM yourTable2) AND
t2.id2 IS NULL
UNION ALL
SELECT
'SA' + RIGHT('' + CAST(t1.id AS VARCHAR(3)), 3) AS id_missing
FROM cte t1
LEFT JOIN table3 t2
ON t1.id = CAST(RIGHT(t2.id3, 3) AS INT)
WHERE
t1.id < (SELECT MAX(CAST(RIGHT(id3, 3) AS INT)) FROM yourTable3) AND
t2.id3 IS NULL
You may use a calendar table approach with a left join here:
WITH cte (id) AS (
SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM sys.all_columns AS s1
CROSS JOIN sys.all_columns AS s2
)
SELECT
'SA' + RIGHT('000' + CAST(t1.id AS VARCHAR(3)), 3) AS id_missing
FROM cte t1
LEFT JOIN yourTable t2
ON t1.id = CAST(RIGHT(t2.id, 3) AS INT)
WHERE
t1.id < (SELECT MAX(CAST(RIGHT(id, 3) AS INT)) FROM yourTable) AND
t2.id IS NULL;
Demo
The idea is to generate a sequence of numbers covering the possible up to 1000 values which might appear in your current table as SAxxx. Then, we left join this calendar table to your current table, on the condition that the numeric portion of the id does not match. All such non matching SAxxx values are then retained in the result set.
I am trying to use Row_Number, it works fine in the order by clause, but when using it in the where clause, i get invalid column, that dosnt make sense to me?
Anybody that can explain why that is? Thanks a bunch
SELECT col1,col2,
ROW_NUMBER() OVER(PARTITION BY col2 ORDER BY col2) as rownr
FROM table1 t1 WITH(NOLOCK)
JOIN table2 t2 WITH(NOLOCK) ON t2.id = t1.id
WHERE rownr > 1
ORDER BY rownr,unit
Logical processing of order by is after the select but where clause is processed before select thats why you get that error.
To do that you should make the query as sub-select and filter the records in outer query
SELECT col1,
col2
FROM (SELECT col1,
col2,
Row_number()OVER(PARTITION BY col2 ORDER BY col2) AS rownr,
unit
FROM table1 t1 WITH(NOLOCK)
JOIN table2 t2 WITH(NOLOCK)
ON t2.id = t1.id) a
WHERE rownr > 1
ORDER BY rownr, unit
check here for more info on Logical Processing Order of the SELECT statement
ROW_NUMBER() cannot be used with same query. Make ORDER BY in outer query.
EDIT : You cannot use rownr in the same query since you are computing ROW_NUMBER() in one place. You can access rownr in an outer query.
SELECT * FROM
(
SELECT col1,col2,unit,
ROW_NUMBER() OVER(PARTITION BY col2 ORDER BY col2) as rownr
FROM table1 t1 WITH(NOLOCK)
JOIN table2 t2 WITH(NOLOCK) ON t2.id = t1.id
)TAB
WHERE rownr > 1
ORDER BY rownr,unit
I want to use left outer join like this:
SELECT ...
FROM Table1
LEFT OUTER JOIN
(SELECT only e.g. 3rd record... , SomeField FROM Table2) tbl2
ON Table1.SomeField = tbl2.SomeField
How can I do that, if I need the subquery to select not just the 3rd record from Table2, but the 3rd record among the Table2 records that have SomeField = Table1.SomeField?
Thanks.
If this is sql server 2005 or newer, you might use row_number():
LEFT JOIN
(
select *
from
(
select *,
row_number() over (order by something) rn
from Table2
where Table2.Column = Table1.Column
) a
where a.rn = 3
) a
Unfortunately you need to nest it a level deeper because you cannot use row_number in a condition directly.
EDIT:
My bad - i didn't really notice the join part. If you want to join derived table, use this:
LEFT JOIN
(
select *,
row_number() over (partition by SomeField order by something) rn
from Table2
) tbl2
ON Table1.SomeField = tbl2.SomeField
AND tbl2.rn = 3
Note: you need ORDER BY in row_number() to keep things consistent.
I need to build an SQL statement to delete from certain table the records that match another select statement.
In Teradata we use
delete from table1
where (col1, col2) in (
select col1,col2
from table2
)
While in SQL Server it's not allowed to have more than 1 column in the WHERE..IN clause. I thought I can use the WITH clause:
with tempTable(col1,col2) as (
select col1,col2
from table2
)
delete from table1
where table1.col1 = tempTable.col1
and table1.col2 = tempTable.col2
How to use WITH..DELETE clause? Is there another way?
This should do it:
DELETE Table1
from Table1 t1
inner join tempTable t2
on t2.Col1 = t1.Col1
and t2.Col2 = t1.Col2
First build a query that selects the rows you need:
SELECT t1.*
FROM [Table1] t1
INNER JOIN [Table2] t2 ON t1.[col1] = t2.[col1] AND t1.[Col2]=t2.[Col2]
Test it to make sure it returns exactly the rows you want to delete. Then turn it into a delete statement by changing the "SELECT" to "DELETE" and removing the column list:
DELETE t1
FROM [Table1] t1
INNER JOIN [Table2] t2 ON t1.[col1] = t2.[col1] AND t1.[Col
delete from table1 t1 where exists
(
select 1 from table2 t2 where t1.col1 = t2.col1 and t1.col2 > t2.col2
)
with tempTable(col1,col2) as (
select col1,col2
from table2
)
delete table1 from tempTable
where table1.col1 = tempTable.col1
and table1.col2 = tempTable.col2
This works for me
WITH CTE AS
(
SELECT TOP 50000 *
from v020101hist order by data
)
DELETE FROM CTE