Select Multiple Columns join SQL Server - sql-server

I have an Employee table like this
And a second table for EmployeeComments with the EmployeeID as foreign key:
I would like to query the employees with their comments in the following format:
select Name, Comment
from Employee emp
left join EmployeeComments empC on empC.EmployeeID = emp.ID
I would like the results to be like:
I have already looked at Pivot, but it doesn't resolve my issue

Use window function:
select case when row_number() over(partition by emp.name order by empC.ID) = 1
then Name
else '' end as Name,
Comment
from Employee emp
left join EmployeeComments empC On empC.EmployeeID = emp.ID

This might give you some kind of order in your result window at least
WITH cte AS(
SELECT emp.Name ,
empC.Comment,
RANK() OVER (ORDER BY emp.Name) NameOrder,
ROW_NUMBER() OVER (PARTITION BY emp.Name ORDER BY empC.ID) RN
FROM Employee emp
LEFT JOIN EmployeeComments empC ON empC.EmployeeID = emp.ID
)
SELECT
Name = (CASE WHEN RN = 1 THEN Name ELSE '' END),
Comment
FROM
cte
ORDER BY
NameOrder,
RN

"use Cross Join:"
Query:
select case t.cnt
when 1 then
coalesce(t.Name,' ')
end as Name,t.comment
from
(
select t1.Name,t2.comment,row_number()
over(partition by t1.name order by t1.Name)
as cnt
from
EmployeeComments t1
cross join
Employee t2
where t1.ID=t2.Employeeid
)t

Related

query is not returning distinct record

Hi can you please take a look why my query is not returning distinct record. i want result with following condition OE1='SCHEDCHNG', need only recent records per orderid or ordernum means only one record per ordernum or orderid and also dropdate is null. My query is as below
select DISTINCT TOP 100 OE.ORDERID,OE.ID,OE.ORDERNUM,OE.OE4 from OrderExports OE
inner join (
select ORDERNUM, max(OE4) as MaxDate
from OrderExports
group by ORDERNUM
) tm
on OE.ORDERNUM = tm.ORDERNUM and OE.OE4 = tm.MaxDate
inner join orde_ O on OE.ORDERID = O.ORDERID
WHERE OE1='SCHEDCHNG' AND O.DROPDATE is null
Pretty sparse on details here but I think you are wanting something along these lines.
with SortedResults as
(
select OE.ORDERID
, OE.ID
, OE.ORDERNUM
, OE.OE4
, ROW_NUMBER() over(partition by OE.ORDERID, OE.ORDERNUM order by OE.OE4 desc) as RowNum
from OrderExports OE
inner join
(
select ORDERNUM
, max(OE4) as MaxDate
from OrderExports
group by ORDERNUM
) tm on OE.ORDERNUM = tm.ORDERNUM and OE.OE4 = tm.MaxDate
inner join orde_ O on OE.ORDERID = O.ORDERID
WHERE OE1='SCHEDCHNG'
AND O.DROPDATE is null
)
select ORDERID
, ID
, ORDERNUM
, OE4
from SortedResults
where RowNum = 1
You can try using max and group by as below :
SELECT a.ID, max(a.ORDERID) as OrderID, max(a.ORDERNUM) as OrderNum,MAX(OE.OE4) as OE4 FROM
(
--your query
) a
group by a.ID

How to list duplicate records?

I have the following table structure:
id|date|studenttypeid|name|audituser
1|.....|4|Jason|....
2|.....|4|Robin|....
3|.....|4|Jason|....
4|.....|4|Dan|....
5|.....|4|Robin|....
I need to list all records which are duplicates on studenttypeid + name.
With the above data, the query should give me the following output:
1|.....|4|Jason|....
2|.....|4|Robin|....
3|.....|4|Jason|....
5|.....|4|Robin|....
How can I achieve this on SQL Server 2008?
You can use a group by and then join back to the original table, like this:
WITH Temp(StudentTypeId, Name) AS(
SELECT
StudentTypeId, Name
FROM YourTable
GROUP BY
StudentTypeId, Name
HAVING Count(1) > 1
)
SELECT YourTable.*
FROM YourTable
INNER JOIN Temp
ON YourTable.StudentTypeId = Temp.StudentTypeId
AND YourTable.Name = Temp.Name
you can use ROW_NUMBER()
SELECT ID, DATE, studenttypeid, name, audituser
FROM
(
SELECT ID, DATE, studenttypeid, name, audituser,
ROW_NUMBER() OVER (PARTITION BY studenttypeid, name
ORDER BY id) rn
FROM yourTableName
) a
WHERE rn = 1
SQLFiddle Demo
If you want to include every occurrence of the duplicates, some more methods using CROSS APPLY...
SELECT p.*
FROM people p
CROSS APPLY (
SELECT TOP(1) * FROM people p2 WHERE p2.ID <> p.ID AND p2.name = p.name AND p.studenttypeid = p2.studenttypeid
) as pWithDups
Or an EXISTS check
SELECT p.*
FROM people p
WHERE EXISTS (
SELECT *
FROM people p2
WHERE p2.ID <> p.ID AND p2.name = p.name AND p.studenttypeid = p2.studenttypeid
)
Try this
SELECT a.*
FROM yourtable a
JOIN (SELECT studenttypeid,
name
FROM yourtable
GROUP BY studenttypeid,
name
HAVING Count(studenttypeid) > 1) b ON b.name = a.name
ORDER BY a.id

Add other column (time) to DISTINCT rows

I am selecting unique rows with
SELECT DISTINCT
LogContent
FROM
[WebAppLog] WITH (NOLOCK)
WHERE
LogName = 'frontendErrorLog'
But how to pair result with other column? I want to select unique LogName and assign it corresponding earliest LogTime just like in:
SELECT
LogTime, LogContent
FROM
[WebAppLog] WITH (NOLOCK)
WHERE
LogName = 'frontendErrorLog'
#Ultra
Will a grouping work for you, like this.
SELECT LogContent,MAX(LogTime) LogTime
FROM [WebAppLog] WITH (NOLOCK)
WHERE LogName = 'frontendErrorLog'
GROUP BY LogContent
You can use ROW_NUMBER:
WITH CTE AS
(
SELECT LogTime, LogContent,
rn = ROW_NUMBER() OVER (PARTITION BY LogContent ORDER BY LogTime ASC)
FROM [WebAppLog] WITH (NOLOCK)
WHERE LogName = 'frontendErrorLog'
)
SELECT LogTime, LogContent FROM CTE WHERE rn = 1

RANK() Over Partition BY not working

When I run the code below the ROWID is always 1.
I need to the ID to start at 1 for each item with the same Credit Value.
;WITH CTETotal AS (SELECT
TranRegion
,TranCustomer
,TranDocNo
,SUM(TranSale) 'CreditValue'
FROM dbo.Transactions
LEFT JOIN customers AS C
ON custregion = tranregion
AND custnumber = trancustomer
LEFT JOIN products AS P
ON prodcode = tranprodcode
GROUP BY
TranRegion
,TranCustomer
,TranDocNo)
SELECT
r.RegionDesc
,suppcodedesc
,t.tranreason as [Reason]
,t.trandocno as [Document Number]
,sum(tranqty) as Qty
,sum(tranmass) as Mass
,sum(transale) as Sale
,cte.CreditValue AS 'Credit Value'
,RANK() OVER (PARTITION BY cte.CreditValue ORDER BY cte.CreditValue)AS ROWID
FROM transactions t
LEFT JOIN dbo.Regions AS r
ON r.RegionCode = TranRegion
LEFT JOIN CTETotal AS cte
ON cte.TranRegion = t.TranRegion
AND cte.TranCustomer = t.TranCustomer
AND cte.TranDocNo = t.TranDocNo
GROUP BY
r.RegionDesc
,suppcodedesc
,t.tranreason
,t.trandocno
,cte.CreditValue
ORDER BY CreditValue ASC
EDIT
All the credit values with 400 must have the ROWID set to 1. And all the credit values with 200 must have the ROWID set to 2. And so on and so on.
Do you need something like this?
with cte (item,CreditValue)
as
(
select 'a',8 as CreditValue union all
select 'b',18 union all
select 'a',8 union all
select 'b',18 union all
select 'a',8
)
select CreditValue,dense_rank() OVER (ORDER BY item)AS ROWID from cte
Result
CreditValue ROWID
----------- --------------------
8 1
8 1
8 1
18 2
18 2
In your code replace
,RANK() OVER (PARTITION BY cte.CreditValue ORDER BY cte.CreditValue)AS ROWID
by
,DENSE_RANK() OVER (ORDER BY cte.CreditValue)AS ROWID
You just don't have to use PARTITION, just DENSE_RANK() OVER (ORDER BY cte.CreditValue)
I think the problem is with the RANK() OVER (PARTITION BY clause
you have to partition it by item not by CreditValue
Try this
RANK() OVER (PARTITION BY cte.CreditValue ORDER BY cte.RegionDesc)AS ROWID
Edit: The issue here isn't actually the nesting of the subquery, it's potentially based on partition by having columns that truly make each row unique (or 1)
Rather than ranking within your complex query like this
select
rank() over(partition by...),
*
from
data_source
join table1
join table2
join table3
join table4
order by
some_column
Try rank() or row_number() on the resulting data set, not within it.
For example, using the query above, remove rank() and implement it this way:
select
rank() over(partition by...),
results.*
from (
select
*
from
data_source
join table1
join table2
join table3
join table4
order by
some_column
) as results

select top 1 with a group by

I have two columns:
namecode name
050125 chris
050125 tof
050125 tof
050130 chris
050131 tof
I want to group by namecode, and return only the name with the most number of occurrences. In this instance, the result would be
050125 tof
050130 chris
050131 tof
This is with SQL Server 2000
I usually use ROW_NUMBER() to achieve this. Not sure how it performs against various data sets, but we haven't had any performance issues as a result of using ROW_NUMBER.
The PARTITION BY clause specifies which value to "group" the row numbers by, and the ORDER BY clause specifies how the records within each "group" should be sorted. So partition the data set by NameCode, and get all records with a Row Number of 1 (that is, the first record in each partition, ordered by the ORDER BY clause).
SELECT
i.NameCode,
i.Name
FROM
(
SELECT
RowNumber = ROW_NUMBER() OVER (PARTITION BY t.NameCode ORDER BY t.Name),
t.NameCode,
t.Name
FROM
MyTable t
) i
WHERE
i.RowNumber = 1;
select distinct namecode
, (
select top 1 name from
(
select namecode, name, count(*)
from myTable i
where i.namecode = o.namecode
group by namecode, name
order by count(*) desc
) x
) as name
from myTable o
SELECT max_table.namecode, count_table2.name
FROM
(SELECT namecode, MAX(count_name) AS max_count
FROM
(SELECT namecode, name, COUNT(name) AS count_name
FROM mytable
GROUP BY namecode, name) AS count_table1
GROUP BY namecode) AS max_table
INNER JOIN
(SELECT namecode, COUNT(name) AS count_name, name
FROM mytable
GROUP BY namecode, name) count_table2
ON max_table.namecode = count_table2.namecode AND
count_table2.count_name = max_table.max_count
I did not try but this should work,
select top 1 t2.* from (
select namecode, count(*) count from temp
group by namecode) t1 join temp t2 on t1.namecode = t2.namecode
order by t1.count desc
Here are to examples that you could use but the temp table use is more efficient than the view, but was done on a small data sample. You would want to check your own statistics.
--Creating A View
GO
CREATE VIEW StateStoreSales AS
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales'
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank'
FROM [dbo].[sales] s
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id)
GROUP BY t.state,t.stor_id,t.stor_name
GO
SELECT * FROM StateStoreSales
WHERE Rank <= 1
ORDER BY TotalSales Desc
DROP VIEW StateStoreSales
---Using a Temp Table
SELECT t.state,t.stor_id,t.stor_name,SUM(s.qty) 'TotalSales'
,ROW_NUMBER() OVER (PARTITION BY t.state ORDER BY SUM(s.qty) DESC) AS 'Rank' INTO #TEMP
FROM [dbo].[sales] s
JOIN [dbo].[stores] t ON (s.stor_id = t.stor_id)
GROUP BY t.state,t.stor_id,t.stor_name
SELECT * FROM #TEMP
WHERE Rank <= 1
ORDER BY TotalSales Desc
DROP TABLE #TEMP

Resources