Can't solve this and just haven't been able to wonder what's going wrong:
SELECT
CODE, NAME,
BRANCH, SALESP,
CASE
WHEN SUM(S1) = 0 THEN NULL
ELSE SUM(S1)
END as S1,
CASE
WHEN SUM(V1) = 0 THEN NULL
ELSE SUM(V1)
END as V1,
CASE
WHEN SUM(CHANGE) = 0 THEN NULL
ELSE SUM(CHANGE)
END as CHANGE
FROM
SAESQL7_E03.[dbo].[p1]
WHERE
S1 <> 0
OR CHANGE <> 0
GROUP BY
CODE, NAME, BRANCH, SALESP
Resulting in:
code name branch salesp s1 v1 change
-------------------------------------------------
1 Max A S 20 10 -5
2 Ben A 10 3 5
2 Ben B 20 5 10
The problem is in the 3rd column which is always wrong if a customer is in more than one branch.
(Max's example when customer only in one branch, always right; Ben's example case with two or more branches, first branch always right, following branches always wrong)
The table of origin has the correct data being:
code name branch salesp S1 V1 V2 change
---------------------------------------------------
1 Max A S 20 5 10 -5
2 Ben A 10 8 3 5
2 Ben B 20 10 5 5
CHANGE column comes from:
SUM (V1-V2) AS CHANGE
As far as I can tell, your query is correct and gives the correct answers! Something is wrong; we'll try to find out what. It looks like you're running on Microsoft SQL Server, so that is what I used for my tests.
Here is the origin table:
1> select * from p1;
2> go
code name branch salesp s1 v1 v2 change
----- ---- ------ ------ ---- ---- ---- --------
1 Max A S 20 5 10 -5
2 Ben A NULL 10 8 3 5
2 Ben B NULL 20 10 5 5
(3 rows affected)
Here is your query:
1> SELECT
2> CODE, NAME,
3> BRANCH, SALESP,
4> CASE
5> WHEN SUM(S1) = 0 THEN NULL
6> ELSE SUM(S1)
7> END as S1,
8> CASE
9> WHEN SUM(V1) = 0 THEN NULL
10> ELSE SUM(V1)
11> END as V1,
12> CASE
13> WHEN SUM(CHANGE) = 0 THEN NULL
14> ELSE SUM(CHANGE)
15> END as CHANGE
16> FROM
17> p1
18> WHERE
19> S1 <> 0
20> OR CHANGE <> 0
21> GROUP BY
22> CODE, NAME, BRANCH, SALESP
23> ;
24> go
... and the results:
CODE NAME BRANCH SALESP S1 V1 CHANGE
------ ---- ------ ------ ----- ---- --------
1 Max A S 20 5 -5
2 Ben A NULL 10 8 5
2 Ben B NULL 20 10 5
(3 rows affected)
So something is wrong. Could you try doing a select from the origin table again, please? Does it contain any other data? If not, then
select * from SAESQL7_E03.[dbo].[p1]
would be best.
If there is a lot more data, do this to make sure you include the same rows as used in the query above:
select
code,
name,
branch,
salesp,
s1,
v1,
v2,
change
from
SAESQL7_E03.dbo.p1
where
s1 <> 0
or change <> 0;
V1 in the query seems to return the values from v2 in the source. Is that a clue? Although you are aggregating, there is never more than one value in each group in the source data. Is this just a test with 1 row per group, with the intention to increase the number of rows per group?
Related
I am using SQL developer and have a table called table1 which looks like this (but with loads more data):
item_id seller_id warranty postage_class
------- --------- -------- -------------
14 2 1 2
17 6 1 1
14 2 1 1
14 2 1 2
14 2 1 1
14 2 1 2
I want to identify the percentage of items sent by first class.
If anyone could help me out that would be amazing!
You can use conditional aggregation. The simplest method is probably:
select avg(case when postage_class = 1 then 1.0 else 0 end)
from t;
Note this calculates a ratio between 0 and 1. If you want a "percentage" between 0 and 100, then use 100.0 instead of 1.0.
Some databases make it possible to shorten this even further. For instance, in Postgres, you can do:
select avg( (postage_class = 1)::int )
from t;
suppose this is my table
name status
ab 1
cd 4
ef -2
mn 3
pq -1
xy 2
defination of status:
1,2 = success
3,4 = failure
-1,-2 = error
expected results after order by
(order by status based on success, failure, error)
ab 1
xy 2
cd 4
mn 3
ef -2
pq -1
while simple order by status gives this
ab 1
xy 2
mn 3
cd 4
pq -1
ef -2
Is there a way to sort in expected way, without adding a column that maps similar status to a certain value?
You can use a case statement:
order by (case when status in (1, 2) then 1
when status in (3, 4) then 2
else 3
end)
If you have a reference table, then you can join to that to get the information as well.
I need solution for converting SQL output
I am writing
SELECT Merchant_Master.Merchant_ID,
COUNT(Coupon_Type_ID) AS "Total Coupons",
Coupon_Type_ID,
CASE WHEN Coupon_Type_ID=1
THEN COUNT(Coupon_Type_ID)
END AS "Secret",
CASE WHEN Coupon_Type_ID=2
THEN count(Coupon_Type_ID)
END AS "Hot"
FROM Coupon_Master
INNER JOIN Merchant_Master
ON Coupon_Master.Merchant_ID=Merchant_Master.Merchant_ID
GROUP BY
Coupon_Master.Coupon_Type_ID,
Merchant_Master.Merchant_ID
and getting output as
Merchant_ID Total Coupons Coupon_Type_ID Secret Hot
----------- ------------- -------------- ----------- -----------
20 6 1 6 NULL
22 4 1 4 NULL
22 2 2 NULL 2
23 1 2 NULL 1
24 2 1 2 NULL
25 3 1 3 NULL
25 2 2 NULL 2
But I want output as
Merchant_ID Secret Hot_Coupons
----------- ------ -------------
20 6 0
22 4 2
23 0 1
24 2 0
25 3 2
Please, help me to solve the issue.
Move the CASE expressions inside the aggregates. I've also switched to using SUM rather than COUNT - there is a COUNT variant but it may display a warning about eliminating NULL values that I'd rather avoid.
SELECT Merchant_Master.Merchant_ID,
SUM(CASE WHEN Coupon_Type_ID=1
THEN 1 ELSE 0 END) AS "Secret",
SUM(CASE WHEN Coupon_Type_ID=2
THEN 1 ELSE 0 END) AS "Hot"
FROM Coupon_Master
INNER JOIN Merchant_Master
ON Coupon_Master.Merchant_ID=Merchant_Master.Merchant_ID
GROUP BY
Merchant_Master.Merchant_ID
Place it in a subquery and add group by Merchant_ID, Total, Coupons, Coupon_Type_ID
Aggregate the Secret and hot as SUM
select
...
SUM(secret) as secret,
SUM(Hot_Coupons) as Hot_Coupons
FROM (your original query) raw
group by Merchant_ID, Total, Coupons, Coupon_Type_ID
I'm trying to write a query that will return the closest match from a table. The table represents a hierarchy, and looks like this:
Hier_Code Group1 Group2 Group3
_________ ______ ______ ______
A 1 1 5
AA 1 2 5
AAA 1 2 5
AAB 1 3 5
AB 2 3 5
ABA 2 3 5
ABB 2 3 5
The values I'm searching for may not match perfectly, in which case I'd want them to 'roll-up' to the next level to find the match. For example:
Value Returns:
A 1 1 5 (Perfect match)
AAC 1 2 5 (AA is closest)
AABB 1 3 5 (AAB is closest)
The idea is that you would strip off one character at a time from the search term until you find a match. I've tried doing this with a recursive CTE, and also with a WHILE loop to no avail.
Any suggestions?
Thanks in advance
Try this:
SELECT top 1 Group1, Group2, Group3
FROM temp
WHERE 'AABB' like Hier_Code + '%'
GROUP BY Group1, Group2, Group3
ORDER BY MAX(len(Hier_Code)) desc
Here's a starter that you could use to create some dynamic SQL:
select id from t
where g1 = 1 and g2 = 1 and g3 = 5
union
select id from t
where g1 = 1 and g2 = 1
union
select id from t
where g1 = 1
The default behavior of UNION is to eliminate duplicates, so that after these three selects are executed, no id would occur more than once in the result set.
The problem is that there are several permutations:
{g1, g2, g3}, {g1, g3}, {g1, g2}, {g2, g3}
so you cannot simply pluck the final condition off as I did in my example.
We have a table like this:
id mid mult tr result
----------------------------
1 1 1,35 0 1
2 1 5,85 0 2
3 1 4 1 X
50 2 1,3 1 1
51 2 7 0 2
52 2 4 0 X
99 3 2,45 0 1
100 3 2,2 0 2
101 3 3,3 1 X
105 4 2,3 0 1
106 4 2,4 0 2
107 4 3,2 1 X
111 5 3 1 1
112 5 1,9 0 2
113 5 3,25 0 X
What we need is a query that will bring us a table which will count how many times before, for a specific mid(match), have the same mults(multipliers) for result = 1 and result = x have occurred and group them so that we can count them. Something like
select mult(where result = 1), mult(where result = x), count(1)
The result will be like this
mult_1 mult_x count
------------------------------
1,35 4 33
1,3 4 112
The above states that we have seen 33 matches where the mult for result = 1 was 1,35 AND mult for result = x was 4. Also, we found 112 matches where multi for result = 1 was 1,3 AND for result = x mult was 4 (results are not dependant on the first table).
I find it rather complex myself, but hopefully I made sense. I use SQL Server 2008, so any method is more than welcome.
Here is my (final) solution in action: http://www.sqlfiddle.com/#!3/3a516/7
There are a number of assumptions I'm making here.
I'm assuming that every mid value is going to have at most 1 result value of '1' and 1 result of '2'.
I'm assuming that if you want to specify a mid and have the query run off of that.
This assumption turned out to be wrong.
I'm assuming that you want to include the data for the mid you specify.
This assumption turned out to be wrong, it was every match.
I'm assuming that you want to include every mid (or match) before the mid you specify.
This assumption turned out to be wrong, it was every match.
I'm assuming that for any mult_1 and mult_x combination you find in this way, you want the count of how many times that combination occurs, even if it occurs after the match(mid) that you specified.
This assumption turned out to be wrong, it was just for every match.
If all of these assumptions sound right, then this might create the result you're looking for:
DECLARE #Mid INT = 2
;WITH MatchResults AS
(
SELECT
Mid
, [1] AS MultWithResult1
, [X] AS MultWithResultX
FROM
(
SELECT
Mid
, mult
, result
FROM Matches
WHERE result IN ('1', 'X')
) Base
PIVOT
(
MAX(mult)
FOR result
IN
(
[1]
, [X]
)
) Pivoted
)
SELECT
mult.MultWithResult1 AS mult_1
, mult.MultWithResultX AS mult_x
, COUNT(*) AS [count]
FROM MatchResults mult
GROUP BY mult.MultWithResult1
, mult.MultWithResultX
EDIT: I have edited it based on the response to my answer to what I think he means.
Use this query:
select mult_1, mult_x, count() as count
from Matches M
inner join (select distinct M1.mult as mult_1, MX.mult as mult_x from
matches as M1, matches as MX
where M1.result=1 and MX.result=x) M1x
on (M.mult=M1x.mult_1 and M.result=1) or (M.mult=M1x.mult_x and result=x)
group by mult_1, mult_x
EDIT:
I'm supposing you wnat to get the count of all possible combinations of multipliers of matches with result=1 and matches with result = x.
If this is the case, M1x gives all this possible combinations. And you join all the possible matchea with have any of those combinations, and count them, grouping by the possible set of combinations defined by M1x.