How to implement this requirement? - sql

I have table
** Table:**
MTID code boxnumber
1 10-01 10
1 10-02 10
1 10-03 10
1 10-04 10
1 10-05 10
1 11-01 11
1 11-02 11
1 11-03 11
1 11-04 11
1 11-05 11
1 12-01 12
1 12-02 12
1 12-03 12
2 13 NULL
2 14 NULL
2 15 NULL
2 16 NULL
2 17 NULL
2 18 NULL
2 19 NULL
Requirement:
In return result, MTID 2 all rows and
MTID 1 conatins full box (count(boxnumber) = 5 where MTID = 1)
In the expected result, code = 12-xx WHERE MTID = 1 not return, because it not full box.
The Expected Result
MTID code boxnumber
1 10-01 10
1 10-02 10
1 10-03 10
1 10-04 10
1 10-05 10
1 11-01 11
1 11-02 11
1 11-03 11
1 11-04 11
1 11-05 11
2 13 NULL
2 14 NULL
2 15 NULL
2 16 NULL
2 17 NULL
2 18 NULL
2 19 NULL
Anyone can Help on this?
Thanks.

We can try using COUNT as an analytic function here to assert the count of 5 requirement. Matching rows either belong to MTID = 1 and having a count of 5 boxnumber, or some other value for MTID.
SELECT MTID, code, boxnumber
FROM
(
SELECT *, COUNT(*) OVER (PARTITION BY MTID, boxnumber) cnt
FROM yourTable
) t
WHERE (MTID = 1 AND cnt = 5) OR MTID <> 1;
Demo

Related

Select only data which columns does not have specific corresponding values respectively

image
Select only data which columns does not have specific corresponding values.
Table Values:
1 D675F009-6908-47A4-816A-AD25A68D8514 0
2 7C96A948-B889-4630-BF67-2187ECFA37DC 1
3 FD6DD4B4-6E5D-4282-B421-A849DB4B1D3E 1
4 178B055F-45FF-4951-A9E2-3470B1DE25E9 1
5 FD6DD4B4-6E5D-4282-B421-A849DB4B1D3E 0
6 D675F009-6908-47A4-816A-AD25A68D8514 0
7 59737584-F44F-4B42-AF9C-1550DFEC1EA5 1
8 FD6DD4B4-6E5D-4282-B421-A849DB4B1D3E 1
9 D675F009-6908-47A4-816A-AD25A68D8514 1
10 7C96A948-B889-4630-BF67-2187ECFA37DC 0
11 178B055F-45FF-4951-A9E2-3470B1DE25E9 1
12 016FAF52-8FBF-4C9C-802D-CA9E13071719 0
Don't select values which have:
(D675F009-6908-47A4-816A-AD25A68D8514) have 1 respectively and
(FD6DD4B4-6E5D-4282-B421-A849DB4B1D3E) have 1 respectively
Allow select values:
(D675F009-6908-47A4-816A-AD25A68D8514) have 0
respectively and (FD6DD4B4-6E5D-4282-B421-A849DB4B1D3E) have 0
respectively
Expected Result::
1 D675F009-6908-47A4-816A-AD25A68D8514 0
2 7C96A948-B889-4630-BF67-2187ECFA37DC 1
4 178B055F-45FF-4951-A9E2-3470B1DE25E9 1
5 FD6DD4B4-6E5D-4282-B421-A849DB4B1D3E 0
6 D675F009-6908-47A4-816A-AD25A68D8514 0
7 59737584-F44F-4B42-AF9C-1550DFEC1EA5 1
10 7C96A948-B889-4630-BF67-2187ECFA37DC 0
11 178B055F-45FF-4951-A9E2-3470B1DE25E9 1
12 016FAF52-8FBF-4C9C-802D-CA9E13071719 0
Is this what you want?
Select * from table where
(is_active=1 and
Participant_id NOT IN
('D675F009-6908-47A4-816A-AD25A68D8514', 'FD6DD4B4-6E5D-4282-B421-A849DB4B1D3E' )
) or
is_active=0;

How to order "group" of row?

This is the query:
SELECT WorkTypeId, WorktypeWorkID, LevelID
FROM Worktypes as w
LEFT JOIN WorktypesWorks as ww on w.ID = ww.WorktypeID
LEFT JOIN WorktypesWorksLevels as wwl on ww.ID = wwl.WorktypeWorkID
This is the result:
WorkTypeId WorktypeWorkID LevelID
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 4 1
1 4 2
1 5 1
NULL NULL NULL
3 19 2
4 6 1
4 7 1
4 7 2
4 7 3
4 17 1
4 17 2
4 18 1
4 18 2
NULL NULL NULL
I'd like to order the block of rows of each WorktypeWorkID, placing at the top the blocks which have the lower LevelID within the block.
Here's the result that I'd like to get:
WorkTypeId WorktypeWorkID LevelID
NULL NULL NULL
NULL NULL NULL
1 3 1 // blocks which have MinLevel 1
1 5 1
4 6 1
1 4 1 // blocks which have MinLevel 2
1 4 2
3 19 2
4 17 1
4 17 2
4 18 1
4 18 2
1 1 1 // blocks which have MinLevel 3
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
4 7 1
4 7 2
4 7 3
I think this is what you are looking for:
SELECT WorkTypeId, WorktypeWorkID, LevelID, MAX(LevelID) OVER (PARTITION BY WorktypeWorkID) as maxLevelID
FROM Worktypes as w
LEFT JOIN WorktypesWorks as ww on w.ID = ww.WorktypeID
LEFT JOIN WorktypesWorksLevels as wwl on ww.ID = wwl.WorktypeWorkID
ORDER BY maxLevelID

summarising a 3 months sales report across 2 branches into top 3 product for each month

I have the following REPORT table
m = month,
pid = product_id,
bid = branch_id,
s = sales
m pid bid s
--------------------------
1 1 1 20
1 3 1 11
1 2 1 14
1 4 1 16
1 5 1 31
1 1 2 30
1 3 2 10
1 2 2 24
1 4 2 17
1 5 2 41
2 3 1 43
2 5 1 21
2 4 1 10
2 1 1 5
2 2 1 12
2 3 2 22
2 5 2 10
2 4 2 5
2 1 2 4
2 2 2 10
3 3 1 21
3 5 1 10
3 4 1 44
3 1 1 4
3 2 1 14
3 3 2 10
3 5 2 5
3 4 2 6
3 1 2 7
3 2 2 10
I'd like to have a summary of this sales table
by showing the top 3 sales among the products across all branches.
something like this:
m pid total
---------------------
1 5 72
1 1 50
1 4 33
2 3 65
2 5 31
2 2 22
3 4 50
3 3 31
3 2 24
so on month 1, product #5 has the highest total sales with 72, followed by product #1 is 50.. and so on. if i could separate them into different table for each month would be better
so far what i can do is make a summary for 1 month and shows the entire thing and not top 3.
select pid, sum(s)
from report
where m = 1
group by pid
order by sum(s);
thanks a lot!
Most databases support the ANSI standard window functions. You can do what you want with row_number():
select m, pid, s
from (select r.m, r.pid, sum(s) as s,
row_number() over (partition by m order by sum(s) desc) as seqnum
from report r
group by r.m, r.pid
) r
where seqnum <= 3
order by m, s desc;

SQL - create pivot table/cross tab from raw data

What is the best way to transform the layout of a flat table into a crosstab/pivot table with SQL.
there is no need to calculations.
The first column of the raw table will be the first column in PV table, second colum of raw will be spitted in columns (12 distinct values) in PVtable. Values will be then the third column in raw table.
I am having difficulties to transform this layout and I guess I am putting to much cases for this making it hard to read/maintain.
does anyone has an idea how to do it?
Many thanks!
Example, below
RAW:
indx rank score
1 1 59
1 2 15
1 3 17
1 4 7
1 5 56
1 6 13
1 7 7
1 8 3
1 9 7
1 10 10
1 11 2
1 12 181
2 2 16
2 3 19
2 4 7
2 5 79
2 6 20
2 7 13
2 8 5
2 9 10
2 10 18
2 11 5
2 12 268
3 3 12
3 4 6
3 5 56
3 6 10
3 7 9
3 8 5
3 9 8
3 10 17
3 11 3
3 12 219
4 4 1
4 5 19
4 6 4
4 7 3
4 8 2
4 9 6
4 10 5
4 11 1
4 12 102
PVtable:
Rank
indx 1 2 3 4 5 6 7 8 9 10 11 12
1 59 15 17 7 56 13 7 3 7 10 2 181
2 - 16 19 7 79 20 13 5 10 18 5 267
3 - - 12 6 56 10 9 5 8 17 3 219
4 - - - 1 19 4 3 2 6 5 1 101
5 - - - - 0 0 0 0 0 0 0 0
6 - - - - - 0 0 0 0 0 0 0
7 - - - - - - 0 0 0 0 0 0
8 - - - - - - - 0 0 0 0 0
9 - - - - - - - - 0 0 0 0
10 - - - - - - - - - 0 0 0
11 - - - - - - - - - - 0 0
12 - - - - - - - - - - - 0
A canonical way that works in just about any database is the conditional aggregation approach:
select indx
max(case when rank = 1 then score end) as rank1,
max(case when rank = 2 then score end) as rank2,
. . .
max(case when rank = 12 then score end) as rank12
from table t
group by indx
order by indx;
In your example, though, it is unclear what indexes of 5 and more all have values of 0.
EDIT:
If you want the values of 5+ to be 0 and to get values from 1-2, then use a left outer join and change the logic in the max():
select n.n as indx,
max(case when rank = 1 then score end) as rank1,
max(case when rank = 2 then score end) as rank2,
. . .
max(case when rank = 12 then score when n.n >= 12 then 0 end) as rank12
from (select 1 as n union all select 2 union all select 3 union all select 4 union all
select 5 union all select 6 union all select 7 union all select 8 union all
select 9 union all select 10 union all select 11 union all select 12
) n left outer join
table t
on n.n = t.indx
group by n.n
order by n.n;

Display Rows only if group of rows' sum is greater then 0

I have a table like the one below. I would like to get this data to SSRS (Grouped by LineID and Product and Column as Hour) to show only those rows where HourCount > 0 for every LineID and Product.
LineID Product Hour HourCount
3 A 0 0
3 A 1 0
3 A 2 0
3 A 3 0
3 A 4 0
3 A 5 0
3 B 0 65
3 B 1 56
3 B 2 45
3 B 3 34
3 B 4 43
3 B 5 45
4 A 0 54
4 A 1 34
4 A 2 45
4 A 3 44
4 A 4 55
4 A 5 44
4 B 0 0
4 B 1 0
4 B 2 0
4 B 3 0
4 B 4 0
4 B 5 0
5 A 0 45
5 A 1 77
5 A 2 66
5 A 3 55
5 A 4 0
5 A 5 0
5 B 0 0
5 B 1 0
5 B 2 45
5 B 3 0
5 B 4 0
5 B 5 0
Basically I would like this table to look like this before it's in SSRS:
LineID Product Hour HourCount
3 B 0 65
3 B 1 56
3 B 2 45
3 B 3 34
3 B 4 43
3 B 5 45
4 A 0 54
4 A 1 34
4 A 2 45
4 A 3 44
4 A 4 55
4 A 5 44
5 A 0 45
5 A 1 77
5 A 2 66
5 A 3 55
5 A 4 0
5 A 5 0
5 B 0 0
5 B 1 0
5 B 2 45
5 B 3 0
5 B 4 0
5 B 5 0
So display Product for the line only if any of the Hourd have HourCount higher then 0.
Is there any query that could give me these results or I should play with display settings in SSRS?
Something like this should work:
with NonZero as
(
select *
, GroupZeroCount = sum(HourCount) over (partition by LineID, Product)
from HourTable
)
select LineID
, Product
, [Hour]
, HourCount
from NonZero
where GroupZeroCount > 0
SQL Fiddle with demo.
You could certainly so something similar in SSRS, but it's certainly much easier and intuitive to apply at the T-SQL level.
I think you are looking for
SELECT LineID,Product,Hour,Count(Hour) AS HourCount
FROM abc
GROUP BY LineID,Productm,Hour HAVING Count(Hour) > 0