Pervasive SQL ignoring Order By after Group By - pervasive

I have a query where i need to group sales by sales rep then client (and currently it is ordered alphabetically sales rep then client) that part work perfectly, but the request recently came that i must sort the query SalesRep (alphabetically), Customers (based on Sales Amount Highest to lowest) and i can not get the query to do that no matter what i do within my knowlage. It just keeps on sorting by SalesRep only as far as i can see.
I'm not sure if it has something to do with the group by or something else i'm doing wrong but i'm officially lost.
Select SM.Description as 'Sales Rep', CM.CustomerDesc,
sum(case when HL.ItemCode Not In ('111','112') then case when HL.DocumentType in (9,11) then HL.DiscountAmount else HL.DiscountAmount*(-1) end end) as 'Product Amount',
sum(case when HL.ItemCode in ('111','112') then case when HL.DocumentType in (9,11) then HL.DiscountAmount else HL.DiscountAmount*(-1) end end) as 'Transport Amount',
max(CM.CashAccount) as CashAccount
from HistoryLines HL
inner join SalesmanMaster SM on SM.Code = HL.SalesmanCode
inner join CustomerMaster CM on CM.CustomerCode = HL.CustomerCode
where`enter code here` HL.DocumentType in (8,9,11)
and HL.DDate between '2018-07-01' and '2018-07-31'
group by SM.Description, CM.CustomerDesc
order by SM.Description, 'Product Amount' DESC;
Below is a example of how the Query above delivers results:
Description |CustomerDesc |Product Amount |Transport |Cash
A Sales Man |M Client |17350 |3425 |0
A Sales Man |B Client |6300 |1343 |1
B Sales Man |A Client |8144 |1782 |0
B Sales Man |H Client |45956.33 |13012.24 |0
B Sales Man |K Client |34255.5 |2484 |0
B Sales Man |N Client |96978.64 |14969.14 |0
B Sales Man |S Client |139720.8 |0 |0
B Sales Man |TH Client |25292.37 |17447.9 |0
B Sales Man |TY Client |14809.6 |0 |0
B Sales Man |V Client |11034 |6307.2 |0
C Sales Man |0 Client |4590 |1350 |0
C Sales Man |AP Client |23706 |3570 |0
C Sales Man |AR Client |26106 |4950 |0
C Sales Man |BU Client |54558.58 |0 |1
C Sales Man |C Client |0 |0 |0
C Sales Man |CI Client |27889.65 |4087.2 |0
C Sales Man |E Client |8204.55 |1250 |0
C Sales Man |F Client |72329.44 |17898 |0
C Sales Man |G Client |4897.8 |1350 |0
C Sales Man |I Client |15167.4 |2700 |0
C Sales Man |J Client |274.8 |0 |0
Thank in advance for any assistance.

Try using the full CASE expression in the ORDER BY clause:
ORDER BY
SM.Description,
SUM(CASE WHEN HL.ItemCode NOT IN ('111','112')
THEN CASE WHEN HL.DocumentType IN (9,11)
THEN HL.DiscountAmount
ELSE HL.DiscountAmount*(-1) END
END) DESC;
I am assuming that the reason you can't use the alias is your database does not support it. Not all SQL databases support using an alias in the ORDER BY clause.
What I think is happening here is that you are ordering by the string literal 'Product Amount', i.e. the intended alias is just being viewed a string. This is why the query is running without error.
Edit:
Based on your comments/testing, your database does support using aliases in the ORDER BY clause. But, you actually presented a string literal. There might be a way to escape Product Amount to use it directly.

Related

Skip an entry WHERE ROW_NUMBER() = X And corresponding entry = 'Y'

I have a table with the ROW_NUMBER() partitioned over the User:
Row|Activity|User
-----------------
1 |A |Jeff
2 |A |Jeff
3 |A |Jeff
1 |A |Bob
2 |B |Bob
3 |C |Bob
1 |A |Sam
2 |B |Sam
3 |A |Sam
4 |D |Sam
I would like to skip, during the row count, the entry 3 for Jeff and Sam because if a User's 3rd Activity is A, I should skip it. I call the to-be-skipped rows 'restricted rows'. Basically, I want this table as a result (Without the comments obviously):
Row|Activity|User
-----------------
1 |A |Jeff
2 |A |Jeff --3rd activity is A so it gets skipped
1 |A |Bob
2 |B |Bob
3 |C |Bob --3rd activity isn't A so it doesn't get skipped
1 |A |Sam
2 |B |Sam --3rd activity is A so it gets skipped
3 |D |Sam
My query:
SELECT ROW_NUMBER() OVER(PARTITION BY User) AS Row, Activity, User FROM Table1
WHERE [Filters]
AND User IN(SELECT User IN Table1
WHERE [Filters] --Same filters as above
GROUP BY User HAVING COUNT(User) > 1) --Let's call this the 'Minimum 1 Activity Filter'
I am going to be perfectly honest, right now, I don't know if the Minimum 1 Activity Filter will cause problems later, aka if Row 2 will also have restrictions. Because of that, I prefer treading on the safe side and imagine that I will have to check the Minimum 1 Activity Filter once all the restricted rows have been taken care of.
if a User's 3rd Activity is A, I should skip it
Consider:
select
row_number() over(partition by user order by id) rn,
activity,
user
from (
select
t.*,
row_number() over(partiton by user order id) rn
from mytable t
) t
where not (rn = 3 and activity = 'A')
Note that, for this to work, you do need a column that can be used to sort the records - I assumed column id.

Average calculation between three factors

I need to calculate the average across the past 5 months(APR, MAY, JUN, JUL, AUG). I have 2 splits to consider: Region(6 regions in total) and Status (between Build and Flow-thru). Currently the data is in a weekly format so I rounded up the weeks to get monthly figures. How do i get the average monthly figure using with the two splits. The table looks something like this:
Region|Orders|BuildStatus|Months
GP |1 |Build |APR
GP |2 |Non-Build |APR
GP |1 |Build |MAY
GP |2 |Non-Build |MAY
PD |1 |Build |APR
PD |2 |Non-Build |APR
PD |1 |Build |MAY
PD |2 |Non-Build |MAY
It repeats with 5 other regions up until August.
Please assist with the correct calculation and if possible you can also suggest the query for it.
The Result should be:
Region|Avg_Orders|BuildStatus
GP |1 |Build
GP |2 |Non-Build
PD |1 |Build
PD |2 |Non-Build
The figures on the average should be the average of the 5 months.
Thanks
DECLARE #t TABLE(
Region NVARCHAR(2)
,Orders INT
,BuildStatus NVARCHAR(100)
,Months NVARCHAR(3)
)
INSERT INTO #t VALUES
('GP', 1,'Build', 'APR')
,('GP', 2,'Non-Build', 'APR')
,('GP', 1,'Build', 'MAY')
,('GP', 2,'Non-Build', 'MAY')
,('PD', 1,'Build', 'APR')
,('PD', 2,'Non-Build', 'APR')
,('PD', 1,'Build', 'MAY')
,('PD', 2,'Non-Build', 'MAY');
WITH cteAgg AS(
SELECT t.Region, t.BuildStatus, SUM(t.Orders) Orders, COUNT(DISTINCT t.Months) MonthsCount
FROM #t t
GROUP BY t.Region, t.BuildStatus
)
SELECT Region, Orders/MonthsCount AS Avg_Orders, BuildStatus
FROM cteAgg
ORDER BY 1

Using MAX in WHERE Clause with < -Operator

I want to select the entries in a table when the registration adress is equal to one (of more than one) delivery adresses AND this adress is the adress where the customer sent all his orders to this adress, since the adress was created.
Date 1 = Date of first order to specific adress, Date 2 = Last/Newest Order to specific adress.To make iot easier to understand... I´ve got this (Table1):
The task:
|cID ||company|Street |Code|del |Street2 |Cod2|Date 1 |Date 2 |
+------------------------------------------------------------------------+
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |DEL St.1|0212|01.01.2015|06.03.2015|
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |REF Wy.1|9875|26.02.2015|16.05.2015|
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |ABC Rd.1|4025|13.06.2015|08.08.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |DEL St.1|0212|13.03.2015|09.07.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |REG St.1|6754|21.02.2015|16.05.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |BLA Rd.5|0897|01.03.2015|06.12.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |HIO Wy.1|9999|09.10.2015|26.11.2015|
|3 ||Ex3 |REG St.1|1114|Ex3 |DEL St.9|0212|13.01.2015|09.02.2015|
|3 ||Ex3 |REG St.1|1114|Ex3 |REG St.1|6754|21.03.2015|16.09.2015|
|3 ||Ex3 |REG St.1|1114|Ex3 |BLA Rd.5|0897|08.06.2015|06.08.2015|
|4 ||Ex4 |FAR RD.9|4567|Ex4 |DDR Wy.2|0897|01.03.2015|06.12.2015|
|4 ||Ex4 |FAR RD.9|4567|Ex4 |FAR RD.9|4567|09.10.2015|26.12.2015|
Expected Result
|cID ||company|Street |Code|del |Street |Code|Date 1 |Date 2 |
+------------------------------------------------------------------------+
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |ABC Rd.1|4025|13.06.2015|08.08.2015|
respectively cID = 1
Here´s what I tried so far, but it´s not working....
SELECT cID
FROM Table1
WHERE company= del
AND Street = Street2
AND Code = Cod2
AND (SELECT MAX (Date 1) > (=! MAX(Date2) FROM Table1 Group by CID)
Edit (To make it more simple to understand):
e.g. the company with the name Ex1 (cID 1) is now located in ABC Rd.1|4025 (actual adress - the adress before is unknown) and has 3 adresses in system, where the orders of the company has been send to.
The first order on adress 1 (DEL St.1|0212) was on 01.01.2015,
the last order to this adress was on 06.03.2015.
The first order on adress 2 (REF Wy.1|9875) was on 26.02.2015
and the last order to this adress was on 16.05.2015 ...
-> I want the cID´s where registration adress (actual adress of the company) is the actual and only delivery adress.
Try using row number to get the latest date.
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER ( PARTITION BY Street, Code, company
ORDER BY Date1 DESC) as rn
FROM Table1
WHERE Street = Street2
AND Code = Cod2
AND company = del
) T
WHERE T.rn = 1
This should work:
SELECT cID
FROM Table1
WHERE Street = Street2
AND Code = Cod2
AND Date1 > (
SELECT MAX(Date2)
FROM Table1 as delivery
WHERE Table1.cID = delivery.cID
AND (delivery.Street2 <> Street OR delivery.Cod2 <> Code)
)
The subquery must itself be a correct SELECT-FROM-WHERE query, and a variable must be used to disambiguate between the outer and inner tables. The inner query selects all deliveries made to the same company but excluding the current delivery, and picks the maximal most recent date. It is then compared to the oldest date of the current delivery address.
Note that the data is not in second normal form. It may be worth, depending on the use case, splitting the table into a table with companies and a table with deliveries.
On my side, it returns 1 as expected.

Sum up delivered companies for every customer(ID)

I'm back in action ;) This time I have a pretty heavy task (I think).
Here's what I got:
|customerID ||company |compdel |Street |Code |Date 1 |Date 2 |
+-------------------------------+--------------------------------------+
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |01.01.2015 |01.08.2015 |
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |13.04.2015 |01.12.2015 |
|1 ||Example1 |DELExam2|DEL St.1|0212 |13.03.2015 |09.07.2015 |
|1 ||Example1 |DELExam3|REF Wy.1|9875 |26.05.2015 |16.09.2015 |
|2 ||Example2 |DELExam4|REG St.1|6754 |21.02.2015 |16.05.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.03.2015 |06.08.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.01.2015 |06.02.2015 |
I want to show for every customerID every delivered company (compdel) summed in one line with the earliest date in Date 1 and the newest Date in Date 2. To make it easier to understand, I want this result:
|customerID ||company |compdel |Street |Code |Date 1 |Date 2 |
+-------------------------------+--------------------------------------+
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |01.01.2015 |01.12.2015 |
|1 ||Example1 |DELExam2|DEL St.1|0212 |13.03.2015 |09.07.2015 |
|1 ||Example1 |DELExam3|REF Wy.1|9875 |26.05.2015 |16.09.2015 |
|2 ||Example2 |DELExam4|REG St.1|6754 |21.02.2015 |16.05.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.01.2015 |06.08.2015 |
I tried it already with this select-Statement but it won´t work: I know, that this can only be a part of the answer....
SELECT *
FROM
(SELECT
customerID, company, compdel, Street, Code, Date 1, Date 2,
ROW_NUMBER() OVER(PARTITION BY compdel ORDER BY customerID) rn
FROM
table 1) as Y
WHERE
rn = 1
Use GROUP BY with distinct values (customerId, company etc.) and MIN and MAX for dates
SELECT CustomerId
, Company
, CompDel
, Street
, Code
, MIN(Date1) As EarliestDate1
, MAX(Date2) AS NewestDate2
FROM YourTable
GROUP BY CustomerId, Company, CompDel, Street, Code

How to get data for below scenario?

I have 4 tables.
Employee:
Id|emp_start_date|Public_id|
01|00-00-00 |001
02|00-00-00 |002
Person:
Id|Public_id|name|...
01|001 |aaaa|..
02|002 |bbbb|...
pay_info:
public_id|current_pay_year
001|2015
002|2015
Ni_table:
public_id|Ni_letter_code|Niable_pay|ni_a|ni_b|ni_c|ni_d|year
001 |A |890 |12 | 12 | 0 | 0 |2015
002 |A |500 |14 |14 |0 | 0 |2015
002 |A |600 |14 |14 |0 | 0 |2015
002 |B |400 |13 | 13 |0 |0 |2015
002 |B |500 |13 | 13 |0 |0 |2015
I want to get the Sum of niable_pay and all other columns by using ni_letter_code for the year 2015.
I want to get all the employees details for current pay year.
But When the employee has two ni letter code, then he should have 2 row for them.
Each row should have the addition value for the respective ni_code.
Expected output:
01|A| 890|12|12|0|0|2015
02|A|1100|25|28|0|0|2015
02|B| 900|26|26|0|0|2015
My query:
select
e.id,
NI.Ni_letter_code,
SUM(NI.Niable_pay),
SUM(ni_a),
SUM(ni_b),
SUM(ni_c),
SUM(ni_d),
ni.year
from
employee e
JOIN person P ON e.id=P.id
INNER JOIN pay_info PI ON PI.public_id = E.public_id
INNER JOIN Ni_table NI ON NI.public_id = E.public_id
AND NI.year = PI.current_pay_year
You seem to think that by stating
select
e.id,
NI.Ni_letter_code,
SUM(NI.Niable_pay),
SUM(ni_a),
SUM(ni_b),
SUM(ni_c),
SUM(ni_d),
ni.year
you get a result record per e.id, NI.Ni_letter_code and ni.year along with the desired sums.
This is not the case. SQL doesn't aggregate by non-aggregated columns implicitely. You must make the aggregation group explicit with GROUP BY. So in order to get one result record per e.id, NI.Ni_letter_code and ni.year you'd add:
group by e.id, NI.Ni_letter_code, ni.year
at the end of your query:
select
e.id,
NI.Ni_letter_code,
SUM(NI.Niable_pay),
SUM(ni_a),
SUM(ni_b),
SUM(ni_c),
SUM(ni_d),
ni.year
from
employee e
JOIN person P ON e.id=P.id
INNER JOIN pay_info PI ON PI.public_id = E.public_id
INNER JOIN Ni_table NI ON NI.public_id = E.public_id
AND NI.year = PI.current_pay_year
group by e.id, NI.Ni_letter_code, ni.year;

Resources