Sorting table in sql server - sql-server

My table data like
id LedgerName
1 "105 AAA"
2 "102 sss"
3 "GGGG"
4 "107 BBB"
5 "BBBB"
6 "101 TTT"
i want sorting the Ledger like
6 "101 TTT"
2 "102 sss"
1 "105 AAA"
4 "107 BBB"
5 "BBBB"
3 "GGGG"
Normal Order by is not working.
i used split function to split for number based sorting in order by ..
how to fix this issue

With the data you have provided a regular order by on LedgerName is doing what you want.
Below is version that deals with data that is a bit more complicated.
SQL Fiddle
MS SQL Server 2008 Schema Setup:
create table YourTable
(
id int,
LedgerName varchar(20)
)
insert into YourTable values
(1, '105 AAA' ),
(2, '1020 sss' ),
(3, ' ' ),
(4, null ),
(5, '0' ),
(6, '999 sss' ),
(7, '9999 sss' ),
(8, 'GGGG' ),
(9, '107 BBB' ),
(10, 'BBBB' ),
(11, '101 TTT' )
Query 1:
select id,
LedgerName
from YourTable
order by case when patindex('%[^0-9]%', isnull(LedgerName, '')+' ') = 1 then 1 else 0 end,
cast(left(LedgerName, patindex('%[^0-9]%', LedgerName+' ')-1) as int),
LedgerName
Results:
| ID | LEDGERNAME |
-------------------
| 5 | 0 |
| 11 | 101 TTT |
| 1 | 105 AAA |
| 9 | 107 BBB |
| 6 | 999 sss |
| 2 | 1020 sss |
| 7 | 9999 sss |
| 4 | (null) |
| 3 | |
| 10 | BBBB |
| 8 | GGGG |

Related

How to build a delimited string using column names if the field is empty?

I did some searching, and most returned the table names or was a bit over-kill for my needs (replacing data..if higher/lower..etc)
I have an existing table I need to work with:
id | booth_100 | booth_101 | booth_102 | booth_103 | booth_105 | booth_121 | booth_200 | booth_201...etc.
My current understanding (didn't create this odd table) is there will only be '1' row
Only '1' of the 'booth_xxx' columns will have a value in it.
How can I build a pipe (|) delimited string using ONLY the 'booth_' column names IF it doesn't have a value in it?
id | booth_100 | booth_101 | booth_102 | booth_103 | booth_105 | booth_121 | booth_200 | booth_201
1 | 1 | 0 | 0 | 0 | 0 1 | 1 | 0
I would like to figure out how to get a returned results of:
booth_100|booth_121|booth200
as my returned query/string.
Is there an easy way to do this? (or some long way that needs to list out every column name in the query itself?.. which I'd still like help with if that's the only route)
SQL Fiddle for table example:
Another example/attempt: (but this one REQUIRES the columns to be bit not int?)..if I use int for col type. the query part fails? (not sure what I am doing wrong though?)
http://sqlfiddle.com/#!18/f80c8/1/0
Your title says "SQL Server" but your sqlfiddle uses MySQL so I'm hoping it is SQL Server you want. The non-normalized table you are using really should be "flipped" or "unpivotted" which you can do using a cross apply as shown below. Once you have the data in a more normalized shape, then you can use STRING_AGG() provided you have SQL Server 2017 or later.
SQL Fiddle
SQL Server 2017 Schema Setup:
create table exhibitors_booth(
id int primary key,
booth_100 int,
booth_101 int,
booth_102 int,
booth_103 int,
booth_104 int,
booth_200 int,
booth_201 int,
booth_202 int,
booth_203 int
);
insert into exhibitors_booth values
('1', 1, 0, 1, 1, 0, 0, 0, 0, 1);
SELECT
CrossApplied.*
into exhibitors
FROM exhibitors_booth
CROSS APPLY (
VALUES
(1, 'booth_100', booth_100)
, (2, 'booth_101', booth_101)
, (3, 'booth_102', booth_102)
, (4, 'booth_103', booth_103)
, (5, 'booth_104', booth_104)
, (6, 'booth_201', booth_200)
, (7, 'booth_202', booth_201)
, (8, 'booth_203', booth_202)
, (9, 'booth_204', booth_203)
) AS CrossApplied(SeqNo, Booth, YesNo)
;
Query 1:
select * from exhibitors_booth
Results:
| id | booth_100 | booth_101 | booth_102 | booth_103 | booth_104 | booth_200 | booth_201 | booth_202 | booth_203 |
|----|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
| 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
Query 2:
select * from exhibitors
Results:
| SeqNo | Booth | YesNo |
|-------|-----------|-------|
| 1 | booth_100 | 1 |
| 2 | booth_101 | 0 |
| 3 | booth_102 | 1 |
| 4 | booth_103 | 1 |
| 5 | booth_104 | 0 |
| 6 | booth_201 | 0 |
| 7 | booth_202 | 0 |
| 8 | booth_203 | 0 |
| 9 | booth_204 | 1 |
Query 3:
select
string_agg(booth,',') as booths
from exhibitors
Results:
| booths |
|-------------------------------------------------------------------------------------------|
| booth_100,booth_101,booth_102,booth_103,booth_104,booth_201,booth_202,booth_203,booth_204 |
I am assuming this is the wanted result. If that's not true please modify your question to include the result you are seeking.
If you do not want to use the "flipped" table just place that code into a cte (or derived table), like this:
with cte as (
SELECT
CrossApplied.*
FROM exhibitors_booth
CROSS APPLY (
VALUES
(1, 'booth_100', booth_100)
, (2, 'booth_101', booth_101)
, (3, 'booth_102', booth_102)
, (4, 'booth_103', booth_103)
, (5, 'booth_104', booth_104)
, (6, 'booth_201', booth_200)
, (7, 'booth_202', booth_201)
, (8, 'booth_203', booth_202)
, (9, 'booth_204', booth_203)
) AS CrossApplied(SeqNo, Booth, YesNo)
)
select
string_agg(booth,',') as booths
from cte
;

How to create a table with columns' names and values from other tables

I have a project for a Shoes-company that needs to join 3 tables. I could do it with DataTable in C# winform but just wonder if I can combine directly in SQL.
Table1 names MoldQty that I will use 3 columns
Model | Size |MoldQuantity
--------------------------
AAA |6.5 | 1
AAA |7 | 2
AAA |7.5 | 1
AAA |8 | 2
AAA |8.5 | 1
AAA |9 | 2
AAA |9.5 | 1
Table 2 names Order that has many other columns
Order Num | Model |
---------------------
20200101xx | AAA |
20200101xy | AAA |
20200101yy | BBB |
Table 3 names OrderDetail
Order Num | Size |Quantity
----------------------------
20200101xx | 6.5 |100
20200101xx | 7.5 |100
20200101xx | 8.5 |200
20200101xy | 7 |100
20200101xy | 8 |100
20200101xy | 9 |200
Now I want to make a Table all Orders for Model AAA with Some columns that Column's name comes from MoldQty.Size and Value come from OrderDetail.Quantity
Order Num | 6.5 | 7 | 7.5 | 8 | 8.5 | 9 | 9.5 |
--------------------------------------------------------------
20200101xx | 100 | Null | 100 | Null | 200 | Null | Null |
20200101xy | Null | 100 | Null | 100 | Null | 100 | Null |
Do anyone have any idea? Thank you so much.
A reference to the MoldQty table is only necessary if the query is made dynamic. Here are sample tables, data, and query.
DROP TABLE IF EXISTS #Order;
GO
CREATE TABLE #Order
(OrderNum CHAR(10) NOT NULL,
Model CHAR(3) NOT NULL
);
GO
INSERT INTO #Order
(OrderNum,
Model
)
VALUES
('20200101xx',
'AAA'
),
('20200101xy',
'AAA'
),
('20200101yy',
'BBB'
);
DROP TABLE IF EXISTS #OrderDetail;
GO
CREATE TABLE #OrderDetail
(OrderNum CHAR(10) NOT NULL,
Size VARCHAR(5) NOT NULL,
Quantity INT NOT NULL
);
GO
INSERT INTO #OrderDetail
(OrderNum,
Size,
Quantity
)
VALUES
('20200101xx',
'6.5',
100
),
('20200101xy',
'7',
100
),
('20200101xx',
'7.5',
200
),
('20200101xy',
'8',
100
),
('20200101xx',
'8.5',
100
),
('20200101xy',
'9',
200
);
SELECT o.OrderNum,
SUM(IIF(od.Size = '6.5', od.Quantity, NULL)) '6.5',
SUM(IIF(od.Size = '7', od.Quantity, NULL)) '7',
SUM(IIF(od.Size = '7.5', od.Quantity, NULL)) '7.5',
SUM(IIF(od.Size = '8', od.Quantity, NULL)) '8',
SUM(IIF(od.Size = '8.5', od.Quantity, NULL)) '8.5',
SUM(IIF(od.Size = '9', od.Quantity, NULL)) '9',
SUM(IIF(od.Size = '9.5', od.Quantity, NULL)) '9.5'
FROM #Order o
JOIN #OrderDetail od ON o.OrderNum = od.OrderNum
WHERE o.Model = 'AAA'
GROUP BY o.OrderNum;
If you want to make the query dynamic, edit the pivot statement to directly insert the Size columns
SELECT * FROM
(
SELECT
OD1.Order_Num,
OD1.Quantity,
mqty.Size
FROM MoldQty AS mqty
INNER JOIN OrderDetail AS OD1
ON OD1.Size = mqty.Size
)[result1]
PIVOT
(
MAX(Quantity)
FOR Size IN([6.5],[7],[7.5],[8],[8.5],[9],[9.5]) -->HERE
)[P1];
+----+------------+------+------+------+------+------+------+------+
| | Order_Num | 6.5 | 7 | 7.5 | 8 | 8.5 | 9 | 9.5 |
+----+------------+------+------+------+------+------+------+------+
| 1 | 20200101xx | 100 | NULL | 100 | NULL | 200 | NULL | NULL |
+----+------------+------+------+------+------+------+------+------+
| 2 | 20200101xy | NULL | 100 | NULL | 100 | NULL | 200 | NULL |
+----+------------+------+------+------+------+------+------+------+
/*
CREATE TABLE MoldQTY(Model nvarchar(50), Size nVarchar(15),MoldQuantity int)
INSERT INTO MoldQTY(Model, Size ,MoldQuantity)
VALUES
('AAA','6.5' ,1),
('AAA','7' ,2),
('AAA','7.5' ,1),
('AAA','8' ,2),
('AAA','8.5' ,1),
('AAA','9' ,2),
('AAA','9.5' ,1)
CREATE TABLE [ORDER1](Order_Num nVarChar(50), Model nVarChar(12))
INSERT INTO [ORDER1](Order_Num, Model)
VALUES
('20200101xx' ,'AAA'),
('20200101xy' ,'AAA'),
('20200101yy' ,'BBB')
CREATE TABLE ORDERDETAIL(Order_Num nVarChar(50) , Size nVarchar(15),Quantity INT)
INSERT INTO ORDERDETAIL(Order_Num, Size, Quantity)
VALUES
('20200101xx' , '6.5' ,100),
('20200101xx' , '7.5' ,100),
('20200101xx' , '8.5' ,200),
('20200101xy' , '7' ,100),
('20200101xy' , '8' ,100),
('20200101xy' , '9' ,200)
--SELECT * FROM MoldQty
--SELECT * FROM ORDER1
--SELECT * FROM ORDERDETAIL
*/

Find largest value in column which was before group by other column

I have to find largest oras_key grouped by acco_key.
So, if acco_key = 5, and occurs in oras_Key = (1,4,5,7), result should be oras_key=7, acco_key = 5 (largest oras_key).
That's one part of the problem.
Other part of the problem:
I have to find all those records - so largest oras_key, grouped by acco_key.
After that, sorting must be done by oras_key.
I've alreday tried grouping but I don't know how to find largest oras_key if I group by acco_key?
Here is table, data and desired output:
+----------+----------+----------+
| oras_key | merc_key | acco_key |
+----------+----------+----------+
| 1 | 3 | 5 |
| 2 | 3 | 6 |
| 3 | 3 | 7 |
| 4 | 3 | 5 |
| 5 | 3 | 5 |
| 7 | 3 | 5 |
| 8 | 3 | 6 |
| 9 | 3 | 6 |
| 10 | 3 | 6 |
| 11 | 3 | 8 |
| 12 | 3 | 8 |
| 13 | 3 | 8 |
| 14 | 3 | 9 |
+----------+----------+----------+
Table definition and data:
declare #tblTemp3 table
(
oras_key int,
merc_key int,
acco_key int
)
insert into #tblTemp3 (oras_key, merc_key, acco_key)
values(1, 3, 5),
(2, 3, 6),
(3, 3, 7),
(4, 3, 5),
(5, 3, 5),
(7, 3, 5),
(8, 3, 6),
(9, 3, 6),
(10, 3, 6),
(11, 3, 8),
(12, 3, 8),
(13, 3, 8),
(14, 3, 9)
Desired output:
+----------+----------+----------+
| oras_key | merc_key | acco_key |
+----------+----------+----------+
| 14 | 3 | 9 |
| 13 | 3 | 8 |
| 10 | 3 | 6 |
| 7 | 3 | 5 |
| 3 | 3 | 7 |
+----------+----------+----------+
You could try this:
;with cte as
(
select r = row_number() over (partition by acco_key order by oras_key desc)
, *
from #tblTemp3
)
select oras_key, merc_key, acco_key
from cte
where r = 1
order by oras_key desc
However, seems like using the MAX() function would do too, if your merc_key is always the same:
select max(oras_key) oras_key, merc_key, acco_key
from #tblTemp3
group by acco_key, merc_key
order by oras_key desc
You can find a demo here.
Select max(oras_key) as oras_key,merc_key ,acco_key from #tblTemp3 group by
acco_key,merc_key
order by 1 desc
Hope this is what you are looking for

How can i get the days between results dates for each seperate pat_id?

I'm looking to get the days between result dates for each patient: only looking at result dates where the result value is <90.00
;WITH patient_results AS (
SELECT * FROM (VALUES
(1, 'EA11AEE3-1D90-4602-9A37-0000007E2293', '85.10' ,'2015-12-11'),
(1, '27BCD3E4-2381-4139-B420-0000025B4113', '91.50' ,'2016-01-05'),
(1, 'D8969360-45D6-487B-AF94-0000035F78B0', '81.00' ,'2016-07-21'),
(5, '446E6413-442A-452A-BCF4-000006AA9896', '58.00' ,'2014-07-01'),
(5, '00305129-BC14-4A12-8368-00000AC04A9B', '53.00' ,'2014-12-13'),
(5, '96A67E53-2D6C-430B-A01F-00000AE4C37B', '42.80' ,'2015-02-01'),
(5, '7C330511-3E99-488C-AF5E-00000BDFA3FF', '54.00' ,'2015-07-01'),
(8, '62A2806A-4969-417A-B4DF-D547621CC594', '89.00' ,'2016-03-10'),
(8, '3B9F4E5B-3433-4F21-850A-FC2127A24B72', '92.60' ,'2016-06-30'),
(8, '1A2D780D-8C11-451C-8A64-6D49140B6232', '88.00' ,'2016-08-05')
) as t (pat_id, visit_id, result_value, result_date))
Based on the above looking to get something like this:
PAT_ID | VISIT_ID | RESULT_VALUE | RESULT_DATE| DAYSBETWEENRESULTDATES
1 | EA11AEE3-1D90-4602-9A37-0000007E2293 | 85.10 | 2015-12-11 | 0
1 | D8969360-45D6-487B-AF94-0000035F78B0 | 81.00 | 2016-07-21 | 223
5 | 446E6413-442A-452A-BCF4-000006AA9896 | 58.00 | 2014-07-01 | 0
5 | 00305129-BC14-4A12-8368-00000AC04A9B | 53.00 | 2014-12-13 | 165
5 | 96A67E53-2D6C-430B-A01F-00000AE4C37B | 42.80 | 2015-02-01 | 50
5 | 7C330511-3E99-488C-AF5E-00000BDFA3FF | 54.00 | 2015-07-01 | 150
8 | 62A2806A-4969-417A-B4DF-D547621CC594 | 89.00 | 2016-03-10 | 0
8 | 1A2D780D-8C11-451C-8A64-6D49140B6232 | 84.00 | 2016-08-05 | 148
I am using Sql Server 2012, Sql server management studio version 11.0.5058.0
Thank you.
Try this.
;WITH patient_results
AS
(
SELECT * FROM
(VALUES (1, 'EA11AEE3-1D90-4602-9A37-0000007E2293', '85.10' ,'2015-12-11'),
(1, '27BCD3E4-2381-4139-B420-0000025B4113', '91.50' ,'2016-01-05'),
(1, 'D8969360-45D6-487B-AF94-0000035F78B0', '81.00' ,'2016-07-21'),
(5, '446E6413-442A-452A-BCF4-000006AA9896', '58.00' ,'2014-07-01'),
(5, '00305129-BC14-4A12-8368-00000AC04A9B', '53.00' ,'2014-12-13'),
(5, '96A67E53-2D6C-430B-A01F-00000AE4C37B', '42.80' ,'2015-02-01'),
(5, '7C330511-3E99-488C-AF5E-00000BDFA3FF', '54.00' ,'2015-07-01'),
(8, '62A2806A-4969-417A-B4DF-D547621CC594', '89.00' ,'2016-03-10'),
(8, '3B9F4E5B-3433-4F21-850A-FC2127A24B72', '92.60' ,'2016-06-30'),
(8, '1A2D780D-8C11-451C-8A64-6D49140B6232', '88.00' ,'2016-08-05') )
as t (pat_id, visit_id, result_value, result_date))
SELECT *, ISNULL(DATEDIFF(DAY, LAG(result_date) OVER(PARTITION BY pat_id ORDER BY result_date), result_date), 0) as daysBetweenResultDates
FROM patient_results
WHERE result_value < 90.00
Result
pat_id visit_id result_value result_date DaysBetweenResultDates
1 EA11AEE3-1D90-4602-9A37-0000007E2293 85.10 2015-12-11 0
1 D8969360-45D6-487B-AF94-0000035F78B0 81.00 2016-07-21 223
5 446E6413-442A-452A-BCF4-000006AA9896 58.00 2014-07-01 0
5 00305129-BC14-4A12-8368-00000AC04A9B 53.00 2014-12-13 165
5 96A67E53-2D6C-430B-A01F-00000AE4C37B 42.80 2015-02-01 50
5 7C330511-3E99-488C-AF5E-00000BDFA3FF 54.00 2015-07-01 150
8 62A2806A-4969-417A-B4DF-D547621CC594 89.00 2016-03-10 0
8 1A2D780D-8C11-451C-8A64-6D49140B6232 88.00 2016-08-05 148
You can use OUTER APPLY to get previous values:
SELECT p.*,
ISNULL(DATEDIFF(DAY,t.result_date,p.result_date),0) AS DaysBetweenResultDates
FROM patient_results p
OUTER APPLY (
SELECT TOP 1 result_date
FROM patient_results
WHERE pat_id = p.pat_id and
result_date < p.result_date and
result_value < 90
ORDER BY result_date DESC) as t
WHERE p.result_value <90

skip records based on columns condition

I have a question in sql server
table name : Emp
Id |Pid |Firstname| LastName | Level
1 |101 | Ram |Kumar | 3
1 |100 | Ravi |Kumar | 2
2 |101 | Jaid |Balu | 10
1 |100 | Hari | Babu | 5
1 |103 | nani | Jai |44
1 |103 | Nani | Balu |10
3 |103 |bani |lalu |20
Here need to retrieve unique records based on id and Pid columns and records which have duplicate records need to skip.
Finally I want output like below
Id |Pid |Firstname| LastName | Level
1 |101 | Ram |Kumar | 3
2 |101 | Jaid |Balu | 10
3 |103 |bani |lalu |20
I found duplicate records based on below query
select id,pid,count(*) from emp group by id,pid having count(*) >=2
this query get duplicated records 2 that records need to skip to retrieve output
please tell me how to write query to achieve this task in sql server.
Since your output is based on unique ID and PID which do not have any duplicate value, You can use COUNT with partition to achieve your desired result.
SQL Fiddle
Sample Data
CREATE TABLE Emp
([Id] int, [Pid] int, [Firstname] varchar(4), [LastName] varchar(5), [Level] int);
INSERT INTO Emp
([Id], [Pid], [Firstname], [LastName], [Level])
VALUES
(1, 101, 'Ram', 'Kumar', 3),
(1, 100, 'Ravi', 'Kumar', 2),
(2, 101, 'Jaid', 'Balu', 10),
(1, 100, 'Hari', 'Babu', 5),
(1, 103, 'nani', 'Jai', 44),
(1, 103, 'Nani', 'Balu', 10),
(3, 103, 'bani', 'lalu', 20);
Query
SELECT *
FROM
(
SELECT *,rn = COUNT(*) OVER(PARTITION BY ID,PID)
FROM Emp
) Emp
WHERE rn = 1
Output
| Id | Pid | Firstname | LastName | Level |
|----|-----|-----------|----------|-------|
| 1 | 101 | Ram | Kumar | 3 |
| 2 | 101 | Jaid | Balu | 10 |
| 3 | 103 | bani | lalu | 20 |

Resources