SQL - Max value for item from different table per group - sql

I have the following SQL tables, with the following data:
site-obj-Prices:
id Parameter Value ActionFunc ActionValue ChainTo ChainOperator GroupID
1 Locality 0 Set 6 NULL NULL 1
2 Locality 1 Set 3 NULL NULL 2
3 Locality 0 Set 15 4 AND 3
4 State 61 Set 15 NULL NULL 3
5 Locality 0 Set 18 6 AND 4
6 State 61 Set 18 7 AND 4
7 AreaCode 954 Set 18 NULL NULL 4
8 Locality 0 Add -1 9 AND 5
9 State 61 Add -1 10 AND 5
10 AreaCode 954 Add -1 11 AND 5
11 Supplier 242 Add -1 NULL NULL 5
12 Weight 3 Add 3 NULL NULL 6
13 Weight 3 Add 2 14 AND 7
14 Supplier 242 Add 2 NULL NULL 7
site-obj-PricesParams:
id Parameter Order
1 Locality 0
2 State 1
3 AreaCode 2
4 Weight 3
5 Supplier 4
And in the following query I need to change ActionLevel so it will reflect
MAX(Order) from [site-obj-PricesParams]
for the all the parameters in each GroupID.
So if I have a group with parameters 'Locality' and 'Weight', ActionLevel should be 3.
Any help will be appreciated.
SELECT
id, Parameter, Value, ActionFunc, ActionValue, ChainTo, ChainOperator, GroupID,
COUNT(GroupID) OVER(PARTITION BY GroupID) AS ActionLevel
FROM
[site-obj-Prices] as Actions
WHERE
GroupID NOT IN (SELECT [GroupID]
FROM [site-obj-Prices] as act
INNER JOIN #ParametersList as par ON act.Parameter = par.sKey
AND act.Value <> par.sValue
UNION
SELECT [GroupID]
FROM [site-obj-Prices] as act
LEFT JOIN #ParametersList as par ON act.Parameter = par.sKey
WHERE par.sKey IS NULL
)
ORDER BY
ActionLevel ASC

If i am not wrong in understanding your requirement then hopefully this would work.
SELECT id,Parameter,Value,ActionFunc,ActionValue,ChainTo,
ChainOperator,GroupID, MAX([Order]) OVER(PARTITION BY GroupID) AS ActionLevel
FROM [site-obj-Prices] as Actions
Inner Join [site-obj-PricesParams] as Params
On Actions.Parameter = Params.Parameter
Where GroupID NOT IN (
SELECT [GroupID]
FROM [site-obj-Prices] as act
INNER JOIN #ParametersList as par
ON act.Parameter=par.sKey AND act.Value<>par.sValue
UNION
SELECT [GroupID]
FROM [site-obj-Prices] as act
LEFT JOIN #ParametersList as par
ON act.Parameter=par.sKey WHERE par.sKey IS NULL
)
ORDER BY ActionLevel ASC

Related

T-SQL How to configure Group by so that specific values would be correctly shown

My current T-SQL query provides the following results:
Query:
WITH CTE AS
(
SELECT SubscriberID, sum(valueMB) as ValuesMB
FROM dbo.InternetNetwork
GROUP BY SubscriberID
),
CTE2 AS (
SELECT ab.planID, a.SubscriberID, MAX(ValuesMB) as MaximumValue
FROM CTE AS a
left join
Subscriber as ab on a.SubscriberID= ab.SubscriberID
GROUP BY ab.planID, a.SubscriberID
)
select *
FROM CTE2 as b
ORDER BY b.MaximumValue desc
Output:
planID | SubscriberID | MaxValue
19 1555 97536.00
18 3528 97478.00
2 4029 93413.00
Query #2:
WITH CTE AS
(
SELECT SubscriberID, sum(valueMB) as ValuesMB
FROM dbo.InternetNetwork
GROUP BY SubscriberID
),
CTE2 AS(
SELECT ab.planID, MAX(ValuesMB) as MaximumValue
FROM CTE AS a
left join
Subscriber as ab on a.SubscriberID= ab.SubscriberID
GROUP BY ab.planID
)
SELECT pl.OperatorID, MAX(b.MaximumValue) as Super
FROM CTE2 as b
left join
Plan as pl on b.planID= pl.planID
GROUP BY pl.operatorID
ORDER BY pl.operatorID
Output #2:
OperatorID | Value
1 93413.00
2 86017.00
3 97536.00
I would like to also include a subscriberID, but I'm unable to figure out a way to do so, as the only way to do it, is including in the last SELECT and adding to GROUP BY, which when done, makes a mess of a result which is not accurate.
My desired output:
OperatorID | Value | SubscriberID
1 93413.00 4029
2 86017.00 164
3 97536.00 1544
internet network data:
SubscriberID ValuesMB
1 28
1 27
2 27
2 27
2 27
3 29
3 28
3 27
3 27
4 27
4 27
4 29
Subscriber Data:
SubscriberID PersonID PlanID
1 1 3
2 2 10
3 2 6
4 3 14
5 3 1
6 4 18
7 5 5
8 5 1
9 5 9
10 5 16
11 6 13
12 6 13
13 6 20
14 6 16
15 7 4
Plan data
PlanID OperatorID
1 1
2 1
3 2
4 2
5 2
6 2
7 2
8 2
9 2
10 2
11 2
12 3
13 3
14 3
15 3
16 3
17 3
18 3
19 3
20 3
The tables are somewhat like this related InternetNetwork-> Subscriber -> Plan. InternetNetwork contains how much each Subscribed has used. Each Subscriber has Plan associated with him. Each Plan contains a different Operator, there are only three. I wish to list all three operators, the data transferred by the subscriber of the plan that has the operator and Subscriber ID.
Window functions allow you to have fields in your select along with aggregate functions. You can do something like this
;WITH CTE AS
(
SELECT I.SubscriberID,
S.PlanID,
SUM(ValuesMB) OVER(PARTITION BY i.SubscriberID)as ValuesMB
FROM dbo.InternetNetwork I
JOIN Subscriber S
ON I.SubscriberID = S.SubscriberID
),
CTE2 AS
(
SELECT p.operatorID,
a.SubscriberID,
a.ValuesMB,
ROW_NUMBER() OVER(PARTITION BY p.operatorID ORDER BY a.ValuesMB DESC) as rn
FROM CTE a
join [Plan] P
on a.planID = P.planID
)
SELECT operatorID,
ValuesMB,
SubscriberID
FROM CTE2
where rn = 1

SQL - Recursively finding count in another table

I have a table which has both category and subcategory such as this :
CategoryID CategoryName ParentCategoryID
1 CatA NULL
2 CatA1 1
3 CatA2 1
4 CatA3 1
5 CatB NULL
6 CatB1 5
7 CatC NULL
8 CatC1 7
I have another table where I have mappings
MappingID CategoryID ItemID
1 2 1
2 3 1
3 6 2
4 8 3
5 2 3
6 3 4
7 4 4
8 2 3
9 3 4
10 2 2
11 2 2
12 2 2
13 2 3
14 2 1
I need a result set where count of all items per category is displayed such as :
Category No. of Items
1 12
5 1
7 1
Could you someone guide me with this?
I have tried using a CTE :
WITH CTE (CategoryID, CategoryName, ParentID, CategoryParentName)
AS
(
SELECT CategoryID,
CategoryName,
ParentCategoryID,
CategoryName AS CategoryParentName
FROM [dbo].[Category]
WHERE ParentCategoryID IS NULL
AND IsDeleted = 0
UNION ALL
SELECT garages.CategoryID,
garages.CategoryName,
garages.ParentCategoryID,
traces.CategoryName AS CategoryParentName
FROM [dbo].[Category] AS garages
INNER JOIN CTE AS traces ON traces.CategoryID= garages.ParentCategoryID
)
SELECT gr.CategoryID, COUNT(map.CategoryID) AS Total
FROM CTE gr
INNER JOIN [dbo].[CategoryMapping] map ON gr.CategoryID = map.CategoryID
GROUP BY gr.CategoryID
If there are just two levels of categories than there is no need for recursive query
select coalesce(c.ParentCategoryID, c.CategoryID), count(*)
from Category c
join CategoryMapping m on c.CategoryID = m.CategoryID
group by coalesce(c.ParentCategoryID, c.CategoryID)
Obviously, categories without mapping won't be there.

filling running total over all month although its null

I have 2 tables. One only with all periods. Second with Account, Amount and period.
I want to build a View that lists Amount kumulated, period and account. Also if I don't have an fact for a period in my table should be appear the period in my view with the last amount.
select distinct
account, b.periode,
SUM(amount) OVER (PARTITION BY account ORDER BY b.periode RANGE UNBOUNDED PRECEDING)
from
fakten a
full join
perioden b on a.periode = b.periode
order by b.periode
it like this:
1 1 6
2 1 4
1 2 13
2 2 3
NULL 3 NULL
1 4 46
2 5 48
NULL 6 NULL
NULL 7 NULL
1 8 147
NULL 9 NULL
NULL 10 NULL
NULL 11 NULL
NULL 12 NULL
I need it like:
1 1 6
2 1 4
1 2 13
2 2 3
1 3 13
2 3 3
1 4 46
2 4 3
1 5 46
2 5 48
1 6 46
2 6 46
and so one...
Any ideas?
full join is not the right approach. Instead, generate the rows you want using a cross join. Then use left join and group by to do the calculation.
select a.account, p.periode,
SUM(f.amount) OVER (PARTITION BY a.account ORDER BY p.periode)
from (select distinct account from fakten) a cross join -- you probably have an account table, use it
perioden p
on a.periode = p.periode left join
fakten f
on f.account = a.account and f.periode = p.periode
group by a.account, p.periode
order by a.account, p.periode;

using sql join on three tables

I have 3 tables which maintains stock entries for each products/items. These three tables like below :
Table : ItemStock (to maintain remaining stock of each item)
Id ItemId OpgQty BranchID CurrentStock
1 7 0 1 8
2 7 0 2 3
3 6 0 1 2
4 6 0 2 0
Table : ItemPurchase (StockIn)
Id ItemId Qty BranchID
1 7 5 1
2 7 4 2
3 7 6 1
4 7 2 2
5 6 4 1
6 6 2 2
7 6 2 1
Table : ItemSale (StockOut)
Id ItemId Qty BranchID
1 7 2 1
2 7 3 2
3 7 1 1
4 6 4 1
5 6 2 2
Desired Output (based on sql queries)
I want to have result like below : (part of report)
Id ItemId OpgQty BranchId StockIn StockOut CurrentStock
1 7 0 1 11 3 8
2 7 0 2 6 3 3
3 6 0 1 6 4 2
4 6 0 2 2 2 0
I was trying to get the desired result but was not able to do so. Please help!!!
try this;
select
m.Id,
m.ItemId,
m.OpgQty,
m.BranchID,
si.StockIn,
m.CurrentStock-si.StockIn StockOut,
m.CurrentStock
from
ItemStock m
inner join
(
select
ItemId,BranchId,sum(Qty) as StockIn
from
ItemPurchase
group by ItemId,BranchId
) si on si.ItemId=m.ItemId and si.BranchId=m.BranchId
A very simple query that gives the desired result is :
select *,
(select sum(Qty)
from ItemPurchase
where ItemPurchase.ItemId = ItemStock.ItemId and
ItemPurchase.BranchId = ItemStock.BranchId) as StockIn,
(select sum(Qty)
from ItemSale
where ItemSale.ItemId = ItemStock.ItemId and
ItemSale.BranchId = ItemStock.BranchId) as StockOut
from ItemStock
Two subqueries with group by and aggregation will get what you want.
select
s.*,
coalesce([ip].StockIn, 0) as StockIn, -- In case of no records in ItemPurchase or ItemSale, coalesce is neccessary.
coalesce([is].StockOut, 0) as StockOut
from ItemStock s
left join (
select sum(Qty) as StockIn, ItemId, BranchId
from ItemPurchase
group by ItemId, BranchId
) [ip] on s.ItemId = [ip].ItemId and s.BranchId = [ip].BranchId
left join (
select sum(Qty) as StockOut, ItemId, BranchId
from ItemSale
group by ItemId, BranchId
) [is] on s.ItemId = [is].ItemId and s.BranchId = [is].BranchId
See demo in sqlfiddle.
Please
Try This ... I hope you consider this too.

Query to serialize data

I have two tables:
Routes
ID Description
1 street1
2 street2
3 street3
4 street4
5 street5
Segments
ID RouteID, Progres, LabelStart, LabelEnd
1 1 5 1 A 21 B
2 1 10 2 A 10
3 2 15 3 25
4 2 15 2 20
5 3 20 1 11
6 3 22 4 10
7 4 30 5 11
8 4 31 2 12
I need a sequence with these rules:
table must be ordered by Progress ASC
A column Type is defined and take O if LabelStart and LabelEnd are Odd, E if Even
if two routes have the same progress then the rows are merged in one where
LabelStart is the minimum (among LabelStart Odd and LabelStart Even)
and LabelEnd is the Max, in this case Type takes the value of A (All)
as per example data above the result should be
Sequence
ID RouteID, Progres, LabelStart, LabelEnd Type
1 1 5 1 A 21 B O
2 1 10 2 A 10 E
4 2 15 2 25 A
5 3 20 1 11 O
6 3 22 4 10 E
7 4 30 5 11 O
8 4 31 2 12 E
It is for Postgres 9.2
This was an interesting query to write because you had letters in your LabelStart and LabelEnd fields. I used REGEX_REPLACE to remove those. Then I used a CTE to get the records that had more than one routeid and progress rows.
I think this should do it:
WITH CTE AS (
SELECT
RouteId, Progress
FROM Sequence
GROUP BY RouteId, Progress
HAVING COUNT(DISTINCT Id) > 1
)
SELECT MAX(S.ID) Id,
T.RouteId,
T.Progress,
MIN(regexp_replace(LabelStart, '[^0-9]', '', 'g')) LabelStart,
MAX(regexp_replace(LabelStart, '[^0-9]', '', 'g')) LabelEnd,
'A' as Type
FROM Sequence S
INNER JOIN CTE T ON S.RouteId = T.RouteId AND S.Progress = T.Progress
GROUP BY T.RouteId, T.Progress
UNION
SELECT S.Id,
S.RouteId,
S.Progress,
S.LabelStart,
S.LabelEnd,
CASE
WHEN CAST(regexp_replace(LabelStart, '[^0-9]', '', 'g') as int) % 2 = 0
THEN 'E'
ELSE 'O'
END
FROM Sequence S
LEFT JOIN CTE T ON S.RouteId = T.RouteId AND S.Progress = T.Progress
WHERE T.RouteId IS NULL
ORDER BY Progress ASC
And some sample Fiddle.