Processing on TSQL Command - sql-server

I have a Data like this
Id TagNo CoreNo FromLocation Device FromTerminal
1 1000 1 AA A1 11
2 1000 2 AA A1 12
3 1000 3 AA A2 13
4 1000 4 AA A2 14
5 1001 1 BB T1 10
I want to have this
TagNo CoreNo FromLocation Device FromTerminal
1000 1 AA A1 11
2 12
3 A2 13
4 14
1001 1 BB T1 10
how can i have it in TSQL / linq?

Formatting the data for display is a job for the application using the data, not the database. There are no specific commands in T-SQL to do what you want.

It can be done, though this is usually handled by a reporting engine (or such).
The following query creates a row number (ROW_NUMBER) per group of duplicate values. Then it only selects the value if it's corresponding row number is 1 by using a CASE.
with mt as (
select
ROW_NUMBER() over (partition by tagNo order by Id) as TagRowNr,
ROW_NUMBER() over (partition by tagNo,FromLoc order by Id) as FromLocRowNr,
ROW_NUMBER() over (partition by tagNo,Device order by Id) as DeviceRowNr,
Id, TagNo, Core, FromLoc, Device, FromTerm
from MyData
)
select
Case when TagRowNr=1 then TagNo else '' end as TagNo,
CoreNo,
Case when FromLocRowNr=1 then FromLoc else '' end as FromLoc,
Case when DeviceRowNr=1 then Device else '' end as Device,
FromTerm
from mt
Order by Id

Related

T-SQL select rows where [col] = MIN([col])

I have a data set produced from a UNION query that aggregates data from 2 sources.
I want to select that data based on whether or not data was found in only of those sources,or both.
The data relevant parts of the set looks like this, there are a number of other columns:
row
preference
group
position
1
1
111
1
2
1
111
2
3
1
111
3
4
1
135
1
5
1
135
2
6
1
135
3
7
2
111
1
8
2
135
1
The [preference] column combined with the [group] column is what I'm trying to filter on, I want to return all the rows that have the same [preference] as the MIN([preference]) for each [group]
The desired output given the data above would be rows 1 -> 6
The [preference] column indicates the original source of the data in the UNION query so a legitimate data set could look like:
row
preference
group
position
1
1
111
1
2
1
111
2
3
1
111
3
4
2
111
1
5
2
135
1
In which case the desired output would be rows 1,2,3, & 5
What I can't work out is how to do (not real code):
SELECT * WHERE [preference] = MIN([preference]) PARTITION BY [group]
One way to do this is using RANK:
SELECT row
, preference
, [group]
, position
FROM (
SELECT row
, preference
, [group]
, position
, RANK() OVER (PARTITION BY [group] ORDER BY preference) AS seq
FROM t) t2
WHERE seq = 1
Demo here
Should by doable via simple inner join:
SELECT t1.*
FROM t AS t1
INNER JOIN (SELECT [group], MIN(preference) AS preference
FROM t
GROUP BY [group]
) t2 ON t1.[group] = t2.[group]
AND t1.preference = t2.preference

sql select based on first minimum value from top

I know we already have a few posts on similar topic. But I think this case a bit different and actually I couldn't get the result I wanted by answers given in other posts.
We have a table as below:
id code amount
------------------
1 A1 80
2 A1 75
3 A1 70
4 A1 70
5 A1 70
1 A2 92
2 A2 85
3 A2 79
4 A2 50
5 A2 50
How can I select the row for "A1" and "A2" based on first lowest value (from top) on "Amount" column? In this case I want the result like below:
id code amount
------------------
3 A1 70
4 A2 50
Thanks!
Use ROW_NUMBER:
SELECT
id, code, amount
FROM (
SELECT *,
Rn = ROW_NUMBER() OVER(PARTITION BY code ORDER BY amount, id)
FROM tbl
) AS t
WHERE Rn = 1
you don't need ordering by id. so correct way would be :
SELECT
id, code, amount
FROM (
SELECT *,
Rn = ROW_NUMBER() OVER(PARTITION BY code ORDER BY amount)
FROM tbl
) AS t
WHERE Rn = 1

How to group a couple of rows in SQL Server?

I have this query:
SELECT
Table1.ID, Table1.Code1, Table1.Code2, Table1.Details,
Table1.IDS, Table2.Name
FROM
Table1
INNER JOIN
Table2 ON Table1.Code1 = Table2.Code1
WHERE
Table1.IDS = 1
ORDER BY
Table1.Code1, Table1.Code2
This is my result for query:
ID Code1 Code2 Details IDS Name
1 1001 01 D1 1 N1
2 1001 01 D2 1 N1
3 1001 02 D3 1 N1
4 1001 05 D4 1 N1
5 1002 11 D5 1 N2
6 1002 12 D6 1 N2
7 1005 21 D7 1 N3
8 1005 21 D8 1 N3
But I want this result:
ID Code1 Code2 Details IDS Name
1 1001 01 D1 1 N1
2 01 D2 1
3 02 D3 1
4 05 D4 1
5 1002 11 D5 1 N2
6 12 D6 1
7 1005 21 D7 1 N3
8 21 D8 1
How do I get this result? Please help me. Thanks a lot
Embedding presentation logic in your query isn't ideal. I recommend you process the query results programmatically, either to detect when groups change as you iterate, or to transform the query results into a nested table. The latter can be generalized as a reusable function.
If you can rely on the ID column for ordering the groups (or a combination of other rows, like code1,code2) then you can do this in a few different ways.
If your server is 2012+ then you can use the LAG() window function to access previous rows and if the previous rows Code1 is the same as the current rows Code1 replace it with null (or an empty string if that suits you better). However, if you're using a version < 2012 then you can accomplish it using a self join.
This kind of formatting might be better to handle on the client side (or reporting layer) though if can.
The query below includes both versions, but I commented out the self-join stuff:
SELECT
Table1.ID,
-- CASE WHEN Table1.Code1 = t1.Code1 THEN NULL ELSE Table1.Code1 END AS Code1,
CASE WHEN LAG(Table1.Code1) OVER (ORDER BY Table1.ID) = Table1.Code1 THEN NULL ELSE Table1.Code1 END AS Code1,
Table1.Code2, Table1.Details, Table1.IDS,
-- CASE WHEN Table1.Name = t1.Name THEN NULL ELSE Table1.Name END AS Name,
CASE WHEN LAG(Table2.Name) OVER (ORDER BY Table1.ID) = Table2.Name THEN NULL ELSE Table2.Name END AS Name
FROM
Table1
INNER JOIN
Table2 ON Table1.Code1 = Table2.Code1
-- LEFT JOIN Table1 t1 ON Table1.ID = t1.ID + 1
WHERE
Table1.IDS = 1
ORDER BY
Table1.Code1, Table1.Code2
Sample SQL Fiddle
Morteza,
This is a clear case of a presentation/UI layer requirement. Databases are made for a particular purpose and that is to crunch data and present you with results. I'd highly recommend you to turn to the front end logic for achieving your purpose.
Using ROW_NUMBER() within CTE or a subquery, here is one way to get your expected output:
;WITH q1 as
(
SELECT
t1.ID,
t1.Code1,
t1.Code2,
t1.Details,
t1.IDS,
t2.Name,
ROW_NUMBER() OVER (PARTITION BY t1.Code1 ORDER BY t1.ID) as rn
FROM
table1 t1
INNER JOIN
Table2 t2 ON t1.Code1 = t2.Code1
)
SELECT
q1.ID,
CASE
WHEN rn = 1 THEN q1.Code1
ELSE ''
END as Code1, --only populate first row for each code1
q1.Code2,
q1.Details,
q1.IDS,
CASE
WHEN rn = 1 THEN q1.Name
ELSE ''
END as Name --only populate first row for each name
FROM
q1
WHERE
q1.IDS = 1
ORDER BY
q1.Code1, q1.Code2
SQL Fiddle Demo

To count rows that is NOT NULL in SSRS

I want to number some base rows in table without mixing the ordering. I have table like this:
Status ProductId
A 12
NULL 25
B 35
C 56
NULL 89
NULL 99
D 120
E 140
I want to add No column, to count Statuses which is not null with same ProductId ordering, but, don't want to count NULL rows. I want the result like this:
No Status ProductId
1 A 12
NULL 25
2 B 35
3 C 56
NULL 89
NULL 99
4 D 120
5 E 140
I work on SQL Sever 2008, SSRS. Someone can give solution in SQL side or in RDL file.
You can do this:
WITH CTE
AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY Status) AS No,
Status, ProductId
FROM table1
WHERE Status IS NOT NULL
)
SELECT
c.No,
t.Status,
t.ProductId
FROM table1 AS t
LEFT JOIN CTE AS c ON c.ProductId = t.ProductId
ORDER BY ProductId;
SQL Fiddle Demo
You can use this query directly in your report.

SQL Server + Select top 1 record of all the distinct records

I am struggling to write a query to result in the following records.
I have a table with records as
c1 c2 c3 c4 c5 c6
1 John 2.3.2010 12:09:54 4 7 99
2 mike 2.3.2010 13:09:59 8 6 88
3 ahmad 2.3.2010 14:09:59 1 9 19
4 Jim 23.3.2010 16:35:14 4 5 99
5 run 23.3.2010 12:09:54 3 8 12
I want to fetch only the records :-
3 ahmad 2.3.2010 14:09:59 1 9 19
4 Jim 23.3.2010 16:35:14 4 5 99
I mean the records that are sort by column c3 and the one which is latest for that day. here i have 1, 2, 3 records that are at different times of the day. there i need the records that are sort by date desc and then only top 1 record. similarly for 4 and 5. can you please help me in writing a query.
If you're on SQL Server 2008 or 2008 R2, you can try this:
WITH TopPerDay AS
(
SELECT
c1, c2, c3, c4, c5, C6,
ROW_NUMBER() OVER
(PARTITION BY CAST(c3 AS DATE) ORDER BY c3 DESC) 'RowNum'
FROM dbo.YourTable
)
SELECT *
FROM TopPerday
WHERE RowNum = 1
I basically partition the data by day (using the DATE type in SQL Server 2008 and up), and order by the c3 column in a descending order. This means, for every day, the oldest row will have RowNum = 1 - so I just select those rows from the Common Table Expression and I'm done.
Tried this on a SQL Server 2005 database.
SELECT *
FROM dbo.YourTable t1
WHERE (t1.c3) =
(
SELECT MAX(t2.c3)
FROM dbo.YourTable t2
WHERE DATEDIFF(dd,t2.c3, t1.c3) = 0
)
ORDER BY t1.c3 ASC
Thanks for the responses!
I have found the solution too.
select * from
(select convert(varchar(10),c3,104) as date, max(c3) as date1 from MYTABLE
group by convert(varchar(10),c3,104)) as T1 innerjoin MYTABLE as T2 on
convert(varchar(10),T2.c3,104) = T1.date and t2.c3 = T2.date1

Resources