Select Query on Sql Server - sql

The question may be very simple but i don't know how to fix it,
I have this table structure
sno left Right
1 2 1
2 2 2
3 1 2
4 3 1
5 2 4
6 7 1
7 2 8
How do I get a result set like the one below
sno left Right Result
1 2 1 1
2 2 2 2
3 1 2 1
4 3 1 1
5 2 4 2
6 7 1 1
7 2 8 2
I wanna select the Data what mimimum value is matched between two columns,
Eg:3 and 1
1 is minimum value between these two and 1 is matched with 3, so the matched value is 1.
eg: 2 and 4
2 is minimum value between these two and 2 is is mathed with 4, so the matched value is 2.
Edited:
If choose 8 and 2 for example
8 contains(1,2,3,4,5,6,7,8)
2 contains(1,2)
So the Result is 2
Because 2 values are matched here.
I hope i explained it well, thanks

The following SQL will return the positive value of a subtraction operation between the left and right values - in a column with Result as the header. It will calculate the difference between left and right values - ABS will make the result positive.
SELECT
sno,
left,
Right,
ABS(left - right) AS Result
FROM tablename

One of the possible solutions:
DECLARE #t TABLE ( sno INT, l INT, r INT )
INSERT INTO #t
VALUES ( 1, 2, 1 ),
( 2, 2, 2 ),
( 3, 1, 2 ),
( 4, 3, 1 ),
( 5, 2, 4 ),
( 6, 7, 1 ),
( 7, 2, 8 )
SELECT *,
(SELECT MIN(v) FROM (VALUES(l),(r)) m(v)) AS m
FROM #t
Output:
sno l r m
1 2 1 1
2 2 2 2
3 1 2 1
4 3 1 1
5 2 4 2
6 7 1 1
7 2 8 2

case
when left < right then left
else right
end

Related

Generate a sequence in SQL based on the column values

I need to generate a sequence in SQL Server 2016 database based on the following logic.
I have three fields each represents ID of Brand, Category and the Product. A brand could have multiple categories and each category could have multiple Products.
I want to generate a Sequence based on the values in these 3 fields
BrandNum
CategoryNum
ProductID
1
1
1
1
2
1
1
1
2
1
2
2
1
3
1
1
4
1
2
1
1
2
1
2
2
1
3
2
1
4
2
1
10
2
1
20
10
10
10
11
9
2
2
10
1
2
1
200
For example if Brand Number is 1, category is 1 and ItemID is 1 then I want 1100001. The first 1 from left represents the Brand Number, second number from left represents the category number and right most number 1 is the item number.
So for other example if the brand number is 4, category is 5 and ItemID is 100 then I need to generate 4500100.
it is working fine with the following logic (there could be a better way of writing it).
Select BrandNum*1000000+CategoryNum*100000+ItemID From Table
It works fine but this logic fails when the brand number is 10, category number is 10 (and any itemID (let's say 120)
The above code gets 1100120 but what I want is 101000120 (first 10 is brand number, second 10 is category number, and next 5 digits is for Item)
Could you please advice me what logic I should use to achieve my output?
It seems like what you ultimately want is a NVARCHAR with segments dedicated to your categories, for the first row:
010100001 because brand is 1 (01) category is 1 (01) and product is 1 (00001).
To get this done you could just cast to NVARCHAR and then pad the resulting string:
DECLARE #Product TABLE (Brand INT, Category INT, Product INT)
INSERT INTO #Product (Brand, Category, Product) VALUES
(1 , 1 , 1 ), (1 , 2 , 1 ), (1 , 1 , 2 ), (1 , 2 , 2 ),
(1 , 3 , 1 ), (1 , 4 , 1 ), (2 , 1 , 1 ), (2 , 1 , 2 ),
(2 , 1 , 3 ), (2 , 1 , 4 ), (2 , 1 , 10 ), (2 , 1 , 20 ),
(10, 10, 10 ), (11, 9 , 2 ), (2 , 10, 1 ), (2 , 1 , 200)
SELECT *, RIGHT('00'+CAST(Brand AS NVARCHAR(2)),2)+RIGHT('00'+CAST(Category AS NVARCHAR(2)),2)+RIGHT('00000'+CAST(Product AS NVARCHAR(5)),5) AS SKU
FROM #Product
Brand Category Product SKU
-------------------------------
1 1 1 010100001
1 2 1 010200001
1 1 2 010100002
1 2 2 010200002
1 3 1 010300001
1 4 1 010400001
2 1 1 020100001
2 1 2 020100002
2 1 3 020100003
2 1 4 020100004
2 1 10 020100010
2 1 20 020100020
10 10 10 101000010
11 9 2 110900002
2 10 1 021000001
2 1 200 020100200
You may use CONCAT and FORMAT functions as the following:
select BrandNum, CategoryNum, ProductID,
concat(BrandNum, CategoryNum, format(ProductID,'00000')) sequence
from table_name
See a demo.

Get combination over two columns

Help me to get SQL
column 1
column 2
Id
DEP-1
1
1
DEP-1
1
2
DEP-1
2
3
DEP-2
3
4
DEP-3
1
5
DEP-3
2
6
DEP-3
3
7
DEP-3
2
8
DEP-3
3
9
I have above table I need to write SQL to display all DISTINCT combination of column 2 over column 1. for example DEP-1 has 1 and 2 in column 2. my final table has to look below.
column 1
column 2
Id
column 2 map
DEP-1
1
1
1~2
DEP-1
1
2
1~2
DEP-1
2
3
1~2
DEP-2
3
4
3
DEP-3
1
5
1~2~3
DEP-3
2
6
1~2~3
DEP-3
3
7
1~2~3
DEP-3
2
8
1~2~3
DEP-3
3
9
1~2~3
select origin.*, c2_map
from origin
join (
select c1, group_concat("~", c2) as c2_map
from (
select distinct c1, c2 from origin
) t1
group by c1
) t2
on origin.c1 = t2.c1
Note:
group_concat(sep, value) is an aggregate function, it depends on the database you use, it means join the values together using sep

SQL From the same table find records shared by common criteria

DB: postgres (PostgreSQL) 10.16 (Ubuntu 10.16-0ubuntu0.18.04.1)
I have a table device_clients in which following data is present:
id
device_id
client_id
1
1
1
2
2
1
3
3
1
4
4
1
5
5
1
6
6
1
7
7
1
8
8
1
9
1
2
10
1
3
11
1
4
12
2
2
13
2
3
14
2
4
15
3
2
16
3
3
17
3
4
I need to find out devices common between each client I provide. For e.g. following are the devices for each client
Client-1 => 1, 2, 3, 4, 5, 6, 7, 8
Client-2 => 1, 2, 3
Client-3 => 1, 2, 3
Client-4 => 1, 2, 3
So for clients 1, 2, 3 the common devices expected are 1, 2, 3.
Can anybody please help me formulate an efficient query to achieve the desired results?
You can use aggregation. For instance:
select device_id
from t
where client_id in (1, 2, 3)
group by device_id
having count(*) = 3;
For convenience, you can pass the list of clients in as an array, allowing you to use:
select device_id
from t
where client_id = any(:client_ar)
group by device_id
having count(*) = cardinality(:client_ar)
You could join the table three times:
select a.device_id
from device_clients a
join device_clients b on b.device_id = a.device_id
join device_clients c on c.device_id = a.device_id
where a.client_id = 1
and b.client_id = 2
and c.client_id = 3

Select rows based on grouped rolling sum condition in Oracle SQL

I have a table like the one below:
ID
RID
Count
1
1
1
2
1
3
3
1
5
4
1
1
5
2
1
6
2
6
7
2
3
8
2
2
9
2
4
I am trying to retrieve the rows of each RID until the rolling sum of Count is ≤ 10.
In this example I need all rows of RID = 1 and only rows 1, 2 and 3 of RID = 2.
Expected answer:
ID
RID
Count
Sum_Count
1
1
1
NULL
2
1
3
4
3
1
5
9
4
1
1
10
5
2
1
NULL
6
2
6
7
7
2
3
10
I tried with ROWNUM, inner query, etc. but nothing worked out.
Can someone please point me in the right direction?
You need to use a cumulative sum of Count by RID and then select all rows where the cumulative count is less than or equal to 10.
Try this:
select
*
from
(
select
ID,
RID,
COUNT,
sum(COUNT) over (partition by RID order by ID) as cum_count
from
my_table
)
where
cum_count <= 10

Adding non existing data to SQL query

My SQL query returns the following result (screenshot):
x y count
----------- ----------- -----------
1 1 10
1 2 2
2 4 3
2 5 5
4 1 5
5 1 8
what i want is x, y should always contain 1 to 5 values, even if the query doesn't return them, in the above scenario x is missing 3. How to add the missing values here that are between 1 & 5.
Thanks in Advance
First you need to generate the desired data. You can use a table of numbers for this. Use CROSS JOIN to generate all possible combinations of two tables. Finally, OUTER JOIN the generated data with your table.
In the following query I have used union to build a list of numbers instead of fetching them from a table. But the idea remains same:
SELECT XList.x, YList.y, #temp.count
FROM (
SELECT 1 AS x UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5
) AS XList
CROSS JOIN (
SELECT 1 AS y UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5
) AS YList
LEFT JOIN #temp ON XList.x = #temp.x AND YList.y = #temp.y
Result:
x y count
----------- ----------- -----------
1 1 10
2 1 NULL
3 1 NULL
4 1 5
5 1 8
1 2 2
2 2 NULL
3 2 NULL
4 2 NULL
5 2 NULL
1 3 NULL
2 3 NULL
3 3 NULL
4 3 NULL
5 3 NULL
1 4 NULL
2 4 3
3 4 NULL
4 4 NULL
5 4 NULL
1 5 NULL
2 5 5
3 5 NULL
4 5 NULL
5 5 NULL
You can do it this way:
select t1.x, t2.y, s.count from
(values(1),(2),(3),(4),(5)) t1(x) cross join
(values(1),(2),(3),(4),(5)) t2(y)
left join #temp s on t1.x = s.x and t2.y = s.y