Zone wise and line item wise display of amedments using SQL Server - sql-server

I have a table in which i have columns like SO number, line item number, amendment number and zone.
I need to display the total number of amendments zone wise.
I have 6 zones - a,b,c,d,e,f
so numbers like 1,2 for zone a; 3,4 for zone b; similarly for other zones.
in each so number there might be 1 or more than one line item numbers like 10,20,30 etc.
for each so number there will be just one amendment (i.e., even if an so number has many line item numbers, it will have just one amendment)
now, say in zone a, there are 4 so numbers 1,2,3,4. and in so number 1 there is one line item number 10 and its amendment number is 2. say for so number 2 there are 4 line item numbers 10,20,30,40 and the amendment number is 0. so for this zone a, total number of amendments would be 2 (desired result). how do i do it?
Zone so_number line_item_number amendment_number
a---------- 1 ---------------- 10 ---------------- 2
a---------- 2 ---------------- 10 ---------------- 0
a---------- 2 ---------------- 20 ---------------- 0
a---------- 2 ---------------- 30 ---------------- 0
a ---------- 2 ---------------- 40 ---------------- 0
a ---------- 3 ---------------- 10---------------- 1
a ---------- 4 ---------------- 10 ---------------- 3
a----------- 4 ----------------- 20 ---------------- 3
b ----------- 6 ---------------- 60 ----------------- 6
c------------ 7 ---------------- 80 ----------------- 0
c ---------- 8 ------------------ 10 ----------------- 0
d ------------ 9 ----------------- 10 ----------------- 2
e ------------ 10----------------- 20 ----------------- 3
f ------------ 11----------------- 30 ----------------- 1
f ------------- 11 --------------- 10 ------------------ 1
f ------------- 11 --------------- 20 ------------------- 1
f ------------ 12 ---------------- 10 ------------------ 2
For zone a total number of amendments would be 6, for zone b it would be 6, for c - 0, for d - 2, e - 3, f - 3
a zone may have any number of so numbers, an so number may have any number of line item numbers, but, an so number may have only one amendment number
How do I do it?

i really don't understand your question and your result.
It could seems very simple from my understands
select zone,
sum(amendment_number)
from tablea
group by zone
now my result would be : 9-6-0-2-3-5
Do you only want the last so_number?
select zone,
sumamend
from
(select zone,
sum(amendment_number) as sumamend,
row_number over (partition by zone order by so_number desc) as ord
from tablea
group by zone, so_number) b
where ord = 1
But again i don't have the same result : 6-6-0-2-3-2
if i correctly understand your comment and hoping you have all case in your example you want something like this :
select zone,
sum(amendment_number)
from (select distinct zone,so_number, amendment_number from #test) p
group by zone
it gives the following result : 6-6-0-2-3-3

Related

DAX - Divide a column over itself with different filters to get percentages

In power Pivot I have tables along the lines of:
Table 1
Year
Month
Branch_ID
Store_ID
Article
Value
2022
10
1
1
Sales
100
2022
10
1
2
Sales
200
2022
10
1
2
Operating expenses
50
2022
10
1
1
Operating expenses
80
2022
10
1
2
Cost of Sales
20
2022
10
1
1
Cost of Sales
30
Table 2
Year
Month
Branch_ID
Store_ID
Article
Value
2022
10
1
1
Sales_Ecomm
20
2022
10
1
2
Sales_Ecomm
15
Table 3
| Article |
|--------------------|
| Sales |
| Operating expenses |
| Cost of Sales |
| Sales_Ecomm |
There are multiple branches and months, so these columns may not be ignored.
Table 1 and table 2 are separate. Table 3 is connected to both so that I could build a pivot table.
In the pivot table I want to have all articles re-evaluated as percentage of Sales, i.e. I am trying to get a pivot table along the lines of:
Store ID
Sales
Operating expenses
Cost of Sales
Sales_Ecomm
Value
% of sales
Value
% of sales
Value
% of sales
Value
% of sales
1
100
100.00%
80
80.00%
30
30.00%
20
20.00%
2
200
100.00%
50
25.00%
20
10.00%
15
7.50%
I have a measure
Val. := sum(table1[Value]) + sum(table2[value])
which seems to be working for absolute values of the articles.
However, I can't seem to come up with an appropriate DAX measure for percentages. I have tried:
%_of_Sales := [Val.] / calculate([Val.], filter(table3; table3[Article]="Sales"))
but it only counts Sales as percentage of Sales (100%), yielding #NUM! for other articles in the pivot table.
How do I define a ratio measure so that every article is evaluated against Sales?
You're missing a crucial ALL:
=
DIVIDE(
[Val.],
CALCULATE(
[Val.],
FILTER(
ALL( table3 ),
table3[Article] = "Sales"
)
)
)
which is equivalent to:
=
DIVIDE(
[Val.],
CALCULATE(
[Val.],
table3[Article] = "Sales"
)
)

Convert Month Days Into Weekdays Per Week In SQL

I have a calendar table and I want to show each month in a grid, and when I select a month from the table, I have some row with monthday and weekday columns, but I must convert it to multiple rows per week to show the month in the grid.
my select command to get month info is something like this
SELECT Monthday, Weekday FROM Calendar Where Month = 5
that Results to this :
Monthday | Weekday
--------- --------
1 4
2 5
3 6
4 7
5 1
6 2
7 3
8 4
. .
. .
. .
and I Want to Convert it To Something like this
1 | 2 | 3 | 4 | 5 | 6 | 7
-- --- --- --- --- --- --
1 2 3 4
5 6 7 8 . . .
just like a calendar grid.
I think the answer is by Pivot, but I don't know how, Do you know a solution how to convert my select command?
Let's suppose you have a calendar table with the structure mentioned below, which is populated with a query like the following:
CREATE TABLE Calendar (
TheDate DATE PRIMARY KEY,
YearNumber SMALLINT,
MonthNumber SMALLINT,
DayNumber SMALLINT,
WeekdayNumber SMALLINT
)
INSERT INTO dbo.Calendar (TheDate, YearNumber, MonthNumber, DayNumber, WeekdayNumber)
SELECT x.TheDate,
YEAR(x.TheDate) AS YearNumber, MONTH(x.TheDate) AS MonthNumber, DAY(x.TheDate) AS DayNumber,
(DATEPART(WEEKDAY,x.TheDate)+##DATEFIRST-2)%7+1 AS WeekdayNumber
FROM (
SELECT TOP 365 DATEADD(DAY,N-1,'20210101') AS TheDate
FROM (SELECT ROW_NUMBER() OVER (ORDER BY low) AS N FROM master..spt_values) t
ORDER BY N
) x
The formula for WeekdayNumber is written this way to ignore the SET DATEFIRST setting and always consider Monday as the first day of week. If you prefer another day to be the first in the week, adjust -2 to another value.
To display something like a calendar for a particular month, you can use a query like this:
SELECT * FROM (
SELECT DayNumber, WeekdayNumber,
DENSE_RANK() OVER (ORDER BY DayNumber-WeekdayNumber) AS WeekNumber
FROM dbo.Calendar WHERE YearNumber=2021 AND MonthNumber=5
) t
PIVOT (MAX(DayNumber) FOR WeekdayNumber IN ([1],[2],[3],[4],[5],[6],[7])) p
This produces the following result:
WeekNumber 1 2 3 4 5 6 7
-------------------- ------ ------ ------ ------ ------ ------ ------
1 NULL NULL NULL NULL NULL 1 2
2 3 4 5 6 7 8 9
3 10 11 12 13 14 15 16
4 17 18 19 20 21 22 23
5 24 25 26 27 28 29 30
6 31 NULL NULL NULL NULL NULL NULL
I am using just the DayNumber and WeekdayNumber columns to compute a week number and then I am using PIVOT to arrange the values for DayNumber in the desired format.

Sum values from multiple tables grouping by a common column

I have three tables in MS SQL Server 2014. Each of them holds a couple of numeric values, a description and a date. For the sake of brevety, let's assume the following tables:
table "beverages"
day beverage amount
---------- -------- ------
2018-12-01 water 2
2018-12-01 tea 1
2018-12-01 coffee 7
2018-12-02 water 4
2018-12-02 tea 2
table "meals"
day meal amount
---------- ------ ------
2018-12-01 burger 1
2018-12-01 bread 2
2018-12-02 steak 1
table "fruit"
day fruit amount
---------- ------ ------
2018-12-01 apple 4
2018-12-01 banana 1
2018-12-02 apple 2
Then I have another table holding only a list of dates.
table "dates"
day
----------
2018-12-01
2018-12-02
What I need is a query that returns one row for each of the rows in the dates table, and in each row has the date, the total amount of beverages, the total amount of meals and the total amount of fruit for that day. I do not care for the different types of beverages, meals and fruit, just the sum. The result should be:
expected result
day beverages meals fruit
---------- ----------- ----------- -----------
2018-12-01 10 3 5
2018-12-02 6 1 2
But instead I receive
received result
day beverages meals fruit
---------- ----------- ----------- -----------
2018-12-01 40 18 30
2018-12-02 6 2 4
I already know what the problem is, just not how to fix it. Even worse, I'm sure that I knew the answer once, but now I can't even figure the right search terms to make Google tell me...
When I do the query like this (I used table variables for testing)
SELECT
[d].[day]
,SUM([b].[amount]) AS [beverages]
,SUM([m].[amount]) AS [meals]
,SUM([f].[amount]) AS [fruit]
FROM #dates AS [d]
LEFT OUTER JOIN #beverages AS [b]
ON [d].[day] = [b].[day]
LEFT OUTER JOIN #meals AS [m]
ON [d].[day] = [m].[day]
LEFT OUTER JOIN #fruit AS [f]
ON [d].[day] = [f].[day]
GROUP BY [d].[day]
it sums each row from the different tables more than once, because it returns every possible combination of the three tables. Removing the SUM() and GROUP BY proves that:
day beverages meals fruit
---------- ----------- ----------- -----------
2018-12-01 2 1 4
2018-12-01 2 1 1
2018-12-01 2 2 4
2018-12-01 2 2 1
2018-12-01 1 1 4
2018-12-01 1 1 1
2018-12-01 1 2 4
2018-12-01 1 2 1
2018-12-01 7 1 4
2018-12-01 7 1 1
2018-12-01 7 2 4
2018-12-01 7 2 1
2018-12-02 4 1 2
2018-12-02 2 1 2
So, what do I need to change in the query to make it sum the values for each of the three tables without multiplying it with the number of the rows in the other tables?
Group the Tables before joining like so:
SELECT
[d].[day]
,[b].[amount] AS [beverages]
,[m].[amount] AS [meals]
,[f].[amount] AS [fruit]
FROM #dates AS [d]
LEFT OUTER JOIN (SELECT day, SUM(amount) as amount FROM #beverages GROUP BY day) AS [b]
ON [d].[day] = [b].[day]
LEFT OUTER JOIN (SELECT day, SUM(amount) as amount FROM #meals GROUP BY day) AS [m]
ON [d].[day] = [m].[day]
LEFT OUTER JOIN (SELECT day, SUM(amount) as amount FROM #fruit GROUP BY day) AS [f]
ON [d].[day] = [f].[day]
How about a PIVOT instead?
Example
Select *
From (
Select day,Item='beverage',amount from beverages
Union All
Select day,Item='meals' ,amount from meals
Union All
Select day,Item='fruit' ,amount from fruit
) src
Pivot ( sum(amount) for Item in ([beverages],[meals],[fruit]) ) pvt

Latest record for each user number?

I did search, but the uniqueness of each question makes it hard for me to "translate" it for my dataset.
I have table A named: CLOGS17
With a sub-set of the data and fields shown:
SERIALNO EVDATE SYSNO AREA USRNO
4 2017-01-01 02:03:48.000 1 4 10
4 2017-01-01 02:09:00.000 1 4 10
4 2017-01-01 02:24:44.997 1 6 10
4 2017-01-01 02:56:50.000 1 2 18
5 2017-08-08 02:03:48.000 1 4 10
5 2017-01-09 02:09:00.000 1 4 10
6 2017-04-03 02:24:44.997 1 6 10
8 2017-05-05 02:56:50.000 1 2 18
My goal is to retrieve all records where the combination of SERIALNO + SYSNO + AREA + USRNO has not been used in the last 30 days (inactive user essentiallY) so I can delete that USRNO.
Desired output from above data would be (newest record for each SERIALNO, SYSNO, AREA, and USRNO distinct combination):
SERIALNO EVDATE SYSNO AREA USRNO
4 2017-01-01 02:09:00.000 1 4 10
4 2017-01-01 02:24:44.997 1 6 10
4 2017-01-01 02:56:50.000 1 2 18
5 2017-08-08 02:03:48.000 1 4 10
6 2017-04-03 02:24:44.997 1 6 10
8 2017-05-05 02:56:50.000 1 2 18
I am then able to get only those within the last 30 days.
Given the table data below ("Table B"), it is a list of all stored users:
SERIALNO CONTID SYSNO AREA USRID
36 001 1 * 1
36 001 1 * 18
36 001 1 * 2
36 001 1 * 29
36 001 1 * 36
36 001 1 1 10
This table contains ALL users in the system.
How can I return all the users from Table B that have not been used for a given CONTID, SYSNO, and AREA?
For the first part of your question it would be as simples as a group by of a select on the desired fields:
SELECT SERIALNO,
SYSNO,
AREA,
USRNO,
MAX(EVDATE)
FROM CLOGS17
GROUP BY SERIALNO,
SYSNO,
AREA,
USRNO
Since you didn't provide enough information about the second part. This query will give you the output you show in your question.
So, to get all users that doesn't meet your 30 days criteria (whatever it are), you just do a left join of you user table with the above query seeking the nulls for the query above, like this:
SELECT *
FROM tableb tb LEFT JOIN
(SELECT SERIALNO,
SYSNO,
AREA,
USRNO,
MAX(EVDATE)
FROM CLOGS17
GROUP BY SERIALNO,
SYSNO,
AREA,
USRNO) a
ON tb.SERIALNO = a.SERIALNO,
AND tb.SYSNO = a.SYSNO
AND tb.USRNO = a.USRNO
WHERE a.AREA is null

Query that shows data depending of 2 columns

I'm working on a Report in Visual Basic. It has a query to show the information below.
So, I need a query that sets all the rows that are between 2 values that the user choose. The problem is that the value exists several times.
To explain better:
ID Category_ID SubCategory_ID Description Period_ID Data
----------- ----------- -------------- ------------- ----------- --------
1 1 1 PRUEBA 1 100.00
2 2 5 Total 1 2.00
3 1 1 sgsdg 2 25.00
4 1 1 fsdf 2 5.00
5 1 1 sdf 2 54.00
There will be a lot more of Period_ID. So, if the user chooses Period 1 and Period 5, it will show all the data between Period 1 and Period 5 (i.e. Period1, Period2, Period3, Period4 and Period5).
Is there a query which can do this?
I appreciate your help!
I would do:
Select *
FROM SAMPLE_TABLE
WHERE SAMPLE_TABLE.PERIOD_ID
IN (SELECT ID FROM PERIOD
WHERE ID >= 1 AND ID <= 5)
This is called a subquery. This relies on you have a period table, which I assume you have

Resources