Converting SQL Query in to Linq or in lambda - sql

I am trying to convert it in LINQ but I am not getting success , I would appreciate if someone help me out to convert it in linq or write the query using lambda expression
SELECT MAX('Quality Of Service') AS Category,
COUNT(CASE WHEN t.QualityOfService = 'Excellent' THEN 1 END) AS Excellent,
COUNT(CASE WHEN t.QualityOfService = 'VeryGood' THEN 1 END) AS Very_Good,
COUNT(CASE WHEN t.QualityOfService = 'Good' THEN 1 END) AS Good,
COUNT(CASE WHEN t.QualityOfService = 'Bad' THEN 1 END) AS Bad,
COUNT(CASE WHEN t.QualityOfService = 'Poor' THEN 1 END) AS Poor
FROM Feedbacks t
WHERE t.DateOfVisit BETWEEN '2018-03-29' AND '2018-03-29'
UNION
SELECT MAX('Quality Of Food') AS Category,
COUNT(CASE WHEN t.QualityOfFood = 'Excellent' THEN 1 END) AS Excellent,
COUNT(CASE WHEN t.QualityOfFood = 'VeryGood' THEN 1 END) AS Very_Good,
COUNT(CASE WHEN t.QualityOfFood = 'Good' THEN 1 END) AS Good,
COUNT(CASE WHEN t.QualityOfFood = 'Bad' THEN 1 END) AS Bad,
COUNT(CASE WHEN t.QualityOfFood = 'Poor' THEN 1 END) AS Poor
FROM Feedbacks t
WHERE t.DateOfVisit BETWEEN '2018-03-29' AND '2018-03-29'
UNION
SELECT MAX('Cleanliness Of Lounge') AS Category,
COUNT(CASE WHEN t.CleanlinessOfLounge = 'Excellent' THEN 1 END) AS Excellent,
COUNT(CASE WHEN t.CleanlinessOfLounge = 'VeryGood' THEN 1 END) AS Very_Good,
COUNT(CASE WHEN t.CleanlinessOfLounge = 'Good' THEN 1 END) AS Good,
COUNT(CASE WHEN t.CleanlinessOfLounge = 'Bad' THEN 1 END) AS Bad,
COUNT(CASE WHEN t.CleanlinessOfLounge = 'Poor' THEN 1 END) AS Poor
FROM Feedbacks t
WHERE t.DateOfVisit BETWEEN '2018-03-29' AND '2018-03-29'
UNION
SELECT MAX('Friendliness Of Staff') AS Category,
COUNT(CASE WHEN t.FriendlinessOfStaff = 'Excellent' THEN 1 END) AS Excellent,
COUNT(CASE WHEN t.FriendlinessOfStaff = 'VeryGood' THEN 1 END) AS Very_Good,
COUNT(CASE WHEN t.FriendlinessOfStaff = 'Good' THEN 1 END) AS Good,
COUNT(CASE WHEN t.FriendlinessOfStaff = 'Bad' THEN 1 END) AS Bad,
COUNT(CASE WHEN t.FriendlinessOfStaff = 'Poor' THEN 1 END) AS Poor
FROM Feedbacks t
WHERE t.DateOfVisit BETWEEN '2018-03-29' AND '2018-03-29'
UNION
SELECT MAX('Overall Experience') AS Category,
COUNT(CASE WHEN t.OverAllExperience = 'Excellent' THEN 1 END) AS Excellent,
COUNT(CASE WHEN t.OverAllExperience = 'VeryGood' THEN 1 END) AS Very_Good,
COUNT(CASE WHEN t.OverAllExperience = 'Good' THEN 1 END) AS Good,
COUNT(CASE WHEN t.OverAllExperience = 'Bad' THEN 1 END) AS Bad,
COUNT(CASE WHEN t.OverAllExperience = 'Poor' THEN 1 END) AS Poor
FROM Feedbacks t
WHERE t.DateOfVisit BETWEEN '2018-03-29' AND '2018-03-29'
The result of this query is coming in this way
Category Excellent Very_Good Good Bad Poor
Null 0 0 0 0 0
I have zero feedbacks right now in my table that is why it is showing null in category and all zero's.
My table looks like this
ID QualityOfFood QualityOfServices CleanlinessOfLounge FreindlinessOfStaff OverALLExperience
I asked this type of question but "this type" not the same , so requesting to don't mark it dublicate

I've Found it by using linqer
( from t in
( from t in db.Feedbacks
where
t.DateOfVisit >= "2018-03-29" && t.DateOfVisit <= "2018-03-29"
select new {
Column1 = "Quality Of Service",
Column2 =
t.QualityOfService == "Excellent" ? (System.Int64?)1 : null,
Column3 =
t.QualityOfService == "VeryGood" ? (System.Int64?)1 : null,
Column4 =
t.QualityOfService == "Good" ? (System.Int64?)1 : null,
Column5 =
t.QualityOfService == "Bad" ? (System.Int64?)1 : null,
Column6 =
t.QualityOfService == "Poor" ? (System.Int64?)1 : null,
Dummy = "x"
})
group t by new { t.Dummy } into g
select new {
Category = g.Max(p => "Quality Of Service"),
Excellent = g.Count(p => p.Column2 != null),
Very_Good = g.Count(p => p.Column3 != null),
Good = g.Count(p => p.Column4 != null),
Bad = g.Count(p => p.Column5 != null),
Poor = g.Count(p => p.Column6 != null)
}
).Union
( from t in
( from t in db.Feedbacks
where
t.DateOfVisit >= "2018-03-29" && t.DateOfVisit <= "2018-03-29"
select new {
Column1 = "Quality Of Food",
Column2 =
t.QualityOfFood == "Excellent" ? (System.Int64?)1 : null,
Column3 =
t.QualityOfFood == "VeryGood" ? (System.Int64?)1 : null,
Column4 =
t.QualityOfFood == "Good" ? (System.Int64?)1 : null,
Column5 =
t.QualityOfFood == "Bad" ? (System.Int64?)1 : null,
Column6 =
t.QualityOfFood == "Poor" ? (System.Int64?)1 : null,
Dummy = "x"
})
group t by new { t.Dummy } into g
select new {
Category = g.Max(p => "Quality Of Food"),
Excellent = g.Count(p => p.Column2 != null),
Very_Good = g.Count(p => p.Column3 != null),
Good = g.Count(p => p.Column4 != null),
Bad = g.Count(p => p.Column5 != null),
Poor = g.Count(p => p.Column6 != null)
}
).Union
( from t in
( from t in db.Feedbacks
where
t.DateOfVisit >= "2018-03-29" && t.DateOfVisit <= "2018-03-29"
select new {
Column1 = "Cleanliness Of Lounge",
Column2 =
t.CleanlinessOfLounge == "Excellent" ? (System.Int64?)1 : null,
Column3 =
t.CleanlinessOfLounge == "VeryGood" ? (System.Int64?)1 : null,
Column4 =
t.CleanlinessOfLounge == "Good" ? (System.Int64?)1 : null,
Column5 =
t.CleanlinessOfLounge == "Bad" ? (System.Int64?)1 : null,
Column6 =
t.CleanlinessOfLounge == "Poor" ? (System.Int64?)1 : null,
Dummy = "x"
})
group t by new { t.Dummy } into g
select new {
Category = g.Max(p => "Cleanliness Of Lounge"),
Excellent = g.Count(p => p.Column2 != null),
Very_Good = g.Count(p => p.Column3 != null),
Good = g.Count(p => p.Column4 != null),
Bad = g.Count(p => p.Column5 != null),
Poor = g.Count(p => p.Column6 != null)
}
).Union
( from t in
( from t in db.Feedbacks
where
t.DateOfVisit >= "2018-03-29" && t.DateOfVisit <= "2018-03-29"
select new {
Column1 = "Friendliness Of Staff",
Column2 =
t.FriendlinessOfStaff == "Excellent" ? (System.Int64?)1 : null,
Column3 =
t.FriendlinessOfStaff == "VeryGood" ? (System.Int64?)1 : null,
Column4 =
t.FriendlinessOfStaff == "Good" ? (System.Int64?)1 : null,
Column5 =
t.FriendlinessOfStaff == "Bad" ? (System.Int64?)1 : null,
Column6 =
t.FriendlinessOfStaff == "Poor" ? (System.Int64?)1 : null,
Dummy = "x"
})
group t by new { t.Dummy } into g
select new {
Category = g.Max(p => "Friendliness Of Staff"),
Excellent = g.Count(p => p.Column2 != null),
Very_Good = g.Count(p => p.Column3 != null),
Good = g.Count(p => p.Column4 != null),
Bad = g.Count(p => p.Column5 != null),
Poor = g.Count(p => p.Column6 != null)
}
).Union
( from t in
( from t in db.Feedbacks
where
t.DateOfVisit >= "2018-03-29" && t.DateOfVisit <= "2018-03-29"
select new {
Column1 = "Overall Experience",
Column2 =
t.OverAllExperience == "Excellent" ? (System.Int64?)1 : null,
Column3 =
t.OverAllExperience == "VeryGood" ? (System.Int64?)1 : null,
Column4 =
t.OverAllExperience == "Good" ? (System.Int64?)1 : null,
Column5 =
t.OverAllExperience == "Bad" ? (System.Int64?)1 : null,
Column6 =
t.OverAllExperience == "Poor" ? (System.Int64?)1 : null,
Dummy = "x"
})
group t by new { t.Dummy } into g
select new {
Category = g.Max(p => "Overall Experience"),
Excellent = g.Count(p => p.Column2 != null),
Very_Good = g.Count(p => p.Column3 != null),
Good = g.Count(p => p.Column4 != null),
Bad = g.Count(p => p.Column5 != null),
Poor = g.Count(p => p.Column6 != null)
}
)

Related

HANA SQL Performance

Can someone help me to reshape this code in a proper way. This Code is old one and would like to reshape it. But not sure how to do it better.
SELECT COUNT(*) FROM (
SELECT SRC.CLIENT,SRC.GUID
,COALESCE(SRC.PARTNER_ZSCHEDUL,'') PARTNER_ZSCHEDUL
,COALESCE(SRC.PARTNER_ZSVCUNIT,'') PARTNER_ZSVCUNIT
,COALESCE(SRC.PARTNER_ZPARTAPP,'') PARTNER_ZPARTAPP
,COALESCE(SRC.PARTNER_ZESCOWN,'') PARTNER_ZESCOWN
,COALESCE(SRC.PARTNER_ZESCAPRV,'') PARTNER_ZESCAPRV
,COALESCE(SRC.PARTNER_ZESCRQST,'') PARTNER_ZESCRQST
,COALESCE(SRC.PARTNER_ZPARTORD,'') PARTNER_ZPARTORD
,COALESCE(SRC.PARTNER_ER,'') PARTNER_ER
FROM KCP810_HBP.ZCRMD_ORDERADM_I_EXTN TGT, (
SELECT CLIENT,GUID
, MIN(CASE WHEN PARTNER_FCT = 'ZSCHEDUL' THEN PARTNER END) PARTNER_ZSCHEDUL
, MIN(CASE WHEN PARTNER_FCT = 'ZSVCUNIT' THEN MERGED_PARTNER END) PARTNER_ZSVCUNIT
, MIN(CASE WHEN PARTNER_FCT = 'ZSVCUNIT' THEN PARTNER END) PARTNER_ZSVCUNIT_HR
, MIN(CASE WHEN PARTNER_FCT = 'ZPARTAPP' THEN PARTNER END) PARTNER_ZPARTAPP
, MIN(CASE WHEN PARTNER_FCT = 'ZESCOWN' THEN PARTNER END) PARTNER_ZESCOWN
, MIN(CASE WHEN PARTNER_FCT = 'ZESCAPRV' THEN PARTNER END) PARTNER_ZESCAPRV
, MIN(CASE WHEN PARTNER_FCT = 'ZESCRQST' THEN PARTNER END) PARTNER_ZESCRQST
, MIN(CASE WHEN PARTNER_FCT = 'ZPARTORD' THEN PARTNER END) PARTNER_ZPARTORD
, MIN(CASE WHEN PARTNER_FCT = '00000014' THEN PARTNER END) PARTNER_ER
FROM "_SYS_BIC"."CRM-SV.A-COMMON-VIEWS.Proc.Item/CV_IT_01_PARTNER_ALL" GROUP BY CLIENT,GUID ) SRC
WHERE TGT.CLIENT = SRC.CLIENT
AND TGT.GUID = SRC.GUID
AND ( TGT.PARTNER_ZSCHEDUL != SRC.PARTNER_ZSCHEDUL OR TGT.PARTNER_ZSVCUNIT != SRC.PARTNER_ZSVCUNIT OR
TGT.PARTNER_ZPARTAPP != SRC.PARTNER_ZPARTAPP OR TGT.PARTNER_ZESCOWN != SRC.PARTNER_ZESCOWN OR
TGT.PARTNER_ZESCAPRV != SRC.PARTNER_ZESCAPRV OR TGT.PARTNER_ZESCRQST != SRC.PARTNER_ZESCRQST OR
TGT.PARTNER_ZPARTORD != SRC.PARTNER_ZPARTORD OR TGT.PARTNER_00000014 != SRC.PARTNER_ER));
To improve the speed, if you want to keep using SQL script, firstly you should replace the where statements with a join statement like below:
SELECT COUNT(*) FROM (
SELECT SRC.CLIENT,SRC.GUID
,COALESCE(SRC.PARTNER_ZSCHEDUL,'') PARTNER_ZSCHEDUL
,COALESCE(SRC.PARTNER_ZSVCUNIT,'') PARTNER_ZSVCUNIT
,COALESCE(SRC.PARTNER_ZPARTAPP,'') PARTNER_ZPARTAPP
,COALESCE(SRC.PARTNER_ZESCOWN,'') PARTNER_ZESCOWN
,COALESCE(SRC.PARTNER_ZESCAPRV,'') PARTNER_ZESCAPRV
,COALESCE(SRC.PARTNER_ZESCRQST,'') PARTNER_ZESCRQST
,COALESCE(SRC.PARTNER_ZPARTORD,'') PARTNER_ZPARTORD
,COALESCE(SRC.PARTNER_ER,'') PARTNER_ER
FROM KCP810_HBP.ZCRMD_ORDERADM_I_EXTN TGT
INNER JOIN (
SELECT CLIENT,GUID
, MIN(CASE WHEN PARTNER_FCT = 'ZSCHEDUL' THEN PARTNER END) PARTNER_ZSCHEDUL
, MIN(CASE WHEN PARTNER_FCT = 'ZSVCUNIT' THEN MERGED_PARTNER END) PARTNER_ZSVCUNIT
, MIN(CASE WHEN PARTNER_FCT = 'ZSVCUNIT' THEN PARTNER END) PARTNER_ZSVCUNIT_HR
, MIN(CASE WHEN PARTNER_FCT = 'ZPARTAPP' THEN PARTNER END) PARTNER_ZPARTAPP
, MIN(CASE WHEN PARTNER_FCT = 'ZESCOWN' THEN PARTNER END) PARTNER_ZESCOWN
, MIN(CASE WHEN PARTNER_FCT = 'ZESCAPRV' THEN PARTNER END) PARTNER_ZESCAPRV
, MIN(CASE WHEN PARTNER_FCT = 'ZESCRQST' THEN PARTNER END) PARTNER_ZESCRQST
, MIN(CASE WHEN PARTNER_FCT = 'ZPARTORD' THEN PARTNER END) PARTNER_ZPARTORD
, MIN(CASE WHEN PARTNER_FCT = '00000014' THEN PARTNER END) PARTNER_ER
FROM "_SYS_BIC"."CRM-SV.A-COMMON-VIEWS.Proc.Item/CV_IT_01_PARTNER_ALL" GROUP BY CLIENT,GUID ) SRC
ON TGT.CLIENT = SRC.CLIENT
AND TGT.GUID = SRC.GUID
AND ( TGT.PARTNER_ZSCHEDUL != SRC.PARTNER_ZSCHEDUL
OR TGT.PARTNER_ZSVCUNIT != SRC.PARTNER_ZSVCUNIT
OR TGT.PARTNER_ZPARTAPP != SRC.PARTNER_ZPARTAPP
OR TGT.PARTNER_ZESCOWN != SRC.PARTNER_ZESCOWN
OR TGT.PARTNER_ZESCAPRV != SRC.PARTNER_ZESCAPRV
OR TGT.PARTNER_ZESCRQST != SRC.PARTNER_ZESCRQST
OR TGT.PARTNER_ZPARTORD != SRC.PARTNER_ZPARTORD
OR TGT.PARTNER_00000014 != SRC.PARTNER_ER));
If this doesn't help you, you should use HANA's Analytic Views for which you could read here.

Using GROUP BY/CASE with WHEN or IF

note: edited query below.
I am looking to segment a data set according to two criteria:
If a customer has more or less than 4 txns at a specific restaurant
If a customer has more or less than 24 txns at all the other restaurants in that data set.
I am using a conjunction of GROUP BY, CASE and WHEN or IF. I am not sure which approach is best, if either?
SELECT
COUNT(Customer) AS number_of_customers,
AVG (CASE WHEN ItemPrice LIKE '-%' THEN NULL
WHEN ItemPrice LIKE '0%' THEN NULL
ELSE CAST (ItemPrice AS FLOAT) END) AS avg_item_price,
COUNT(DISTINCT(ReceiptIDDesc)) AS number_of_orders,
SUM(CAST(ItemPrice AS FLOAT)) AS total_spend
FROM Tacos
WHERE NOT (PurchaseDate > '01/01/2016 12:00' OR '03/01/2016 12:00'<
PurchaseDate)
GROUP BY
CASE
WHEN (COUNT('MerchantFamily' = %TacoTruck%)> 2) AND COUNT('MerchantFamily' != %TacoTruck%) >24)
THEN 'Fanatic'
WHEN (COUNT('MerchantFamily' = %TacoTruck%)> 2) AND COUNT('MerchantFamily' != %TacoTruck%) <24)
THEN 'Loyalist'
WHEN (COUNT('MerchantFamily' = %TacoTruck%)< 2) AND COUNT('MerchantFamily' != %TacoTruck%) <24)
THEN 'Seldom'
ELSE
'Potential'
END
OR
GROUP BY
CASE
IF(COUNT(IF( 'MerchantFamily' = 'TacoTruck', 1, 0 ) ) > 2, TRUE, FALSE)
AND
IF(COUNT(IF( 'MerchantFamily' != 'TacoTruck',1, 0) ) < 24, TRUE, FALSE), 'Loyalist', NULL )
IF(COUNT(IF( 'MerchantFamily' = 'TacoTruck', 1, 0 ) ) > 2, TRUE, FALSE)
AND
IF(COUNT(IF( 'MerchantFamily' != 'TacoTruck', 1, 0 ) ) > 24, TRUE, FALSE), 'Fanatic', NULL)
IF(COUNT(IF( 'MerchantFamily' = 'TacoTruck', 1, 0 ) ) < 2, TRUE, FALSE)
AND
IF(COUNT( IF( 'MerchantFamily' != 'TacoTruck', 1, 0 ) ) < 24, TRUE, FALSE), 'Seldom', NULL)
ELSE
'Potential'
END
Neither of those approaches will work, you need to group first then consider the aggregated count values through a having clause, or as a nested subquery ("derived table").
A case expression only evaluates values on a per row basis, it does not scan multiple rows.

Rails Query - Group By with 2 groups

In my website my users have an attribute localidade. This specifies where they live.
I'm trying to do a query where I group the results the following way:
localidade | Number of Users
-------------+--------------
New York | 6
Not New York | 8
I want the number of users from New York and the number of users from anywhere else but New York.
I tried this:
User.group("lower(localidade) = 'new york'").count
but since I don't have any users from new york and only 1 not from New York it returns:
{false => 1}
Am I able to give aliases to groups? Is there any way of grouping this way the results?
I'm gonna use the results for a Pie Graph from Graphkick.
You could write your query :
User.group("lower(localidade)")
.select("CASE WHEN lower(localidade) = 'new york' THEN COUNT(id) END AS NewYork,
CASE WHEN lower(localidade) != 'new york' THEN COUNT(id) END AS Non-NewYork")
Since 9.4, you can use FILTER with aggregate expression :
User.group("lower(localidade)")
.select("COUNT(id) FILTER (WHERE lower(localidade) != 'new york') AS NonNewyork,
COUNT(id) FILTER (WHERE lower(localidade) = 'new york') AS Newyork")
I created a Table to explain and test the above sql, and they worked as expected :
[shreyas#rails_app_test (master)]$ rails db
psql (9.4.1)
Type "help" for help.
app_development=# select id, location, name from people;
id | location | name
----+----------+------
2 | X | foo
3 | X | foo
4 | Y | foo
(3 rows)
app_development=# SELECT COUNT(id) FILTER(WHERE lower(location) != 'x') AS Non_X_loc, COUNT(id) FILTER (WHERE lower(location) = 'x') AS X_loc FROM "people";
non_x_loc | x_loc
-----------+-------
1 | 2
(1 row)
Let me now, jump to the rails console, and test the equivalent Rails code :
[2] pry(main)> p = Person.select("COUNT(id) FILTER(WHERE lower(location) != 'x') AS Non_X_loc, COUNT(id) FILTER (WHERE lower(location) = 'x') AS X_loc ")
Person Load (0.5ms) SELECT COUNT(id) FILTER(WHERE lower(location) != 'x') AS Non_X_loc, COUNT(id) FILTER (WHERE lower(location) = 'x') AS X_loc FROM "people"
=> [#<Person:0x007fd85ed71980 id: nil>]
[3] pry(main)> p.first.attributes
=> {"id"=>nil, "non_x_loc"=>1, "x_loc"=>2}
[6] pry(main)> Person.group("lower(location)").select("CASE WHEN lower(location) = 'x' THEN COUNT(id) END AS X_loc, CASE WHEN lower(location) != 'x' THEN COUNT(id) END AS Non_X_loc")
Person Load (0.6ms) SELECT CASE WHEN lower(location) = 'x' THEN COUNT(id) END AS X_loc, CASE WHEN lower(location) != 'x' THEN COUNT(id) END AS Non_X_loc FROM "people" GROUP BY lower(location)
=> [#<Person:0x007fd8608281e8 id: nil>, #<Person:0x007fd860828008 id: nil>]
[7] pry(main)> p = _
=> [#<Person:0x007fd8608281e8 id: nil>, #<Person:0x007fd860828008 id: nil>]
[8] pry(main)> p.map { |rec| rec.attributes }
=> [{"id"=>nil, "x_loc"=>nil, "non_x_loc"=>1}, {"id"=>nil, "x_loc"=>2, "non_x_loc"=>nil}]
[9] pry(main)> p.map { |rec| rec.attributes.except('id') }
=> [{"x_loc"=>nil, "non_x_loc"=>1}, {"x_loc"=>2, "non_x_loc"=>nil}]
Update
You can remove those nil from DB level only :
Rails code :
[shreyas#rails_app_test (master)]$ rails c
Loading development environment (Rails 4.2.0)
[1] pry(main)> Person.group("lower(location)").select("CASE WHEN lower(location) = 'x' THEN COUNT(id) ELSE 0 END AS X_loc, CASE WHEN lower(location) != 'x' THEN COUNT(id) ELSE 0 END AS Non_X_loc")
Person Load (0.9ms) SELECT CASE WHEN lower(location) = 'x' THEN COUNT(id) ELSE 0 END AS X_loc, CASE WHEN lower(location) != 'x' THEN COUNT(id) ELSE 0 END AS Non_X_loc FROM "people" GROUP BY lower(location)
=> [#<Person:0x007fd858c100b0 id: nil>, #<Person:0x007fd860853e88 id: nil>]
[2] pry(main)> p = _
=> [#<Person:0x007fd858c100b0 id: nil>, #<Person:0x007fd860853e88 id: nil>]
[3] pry(main)> p.map { |rec| rec.attributes }
=> [{"id"=>nil, "x_loc"=>0, "non_x_loc"=>1}, {"id"=>nil, "x_loc"=>2, "non_x_loc"=>0}]
[4] pry(main)> p.map { |rec| rec.attributes.except('id') }
=> [{"x_loc"=>0, "non_x_loc"=>1}, {"x_loc"=>2, "non_x_loc"=>0}]
[5] pry(main)> p = Person.select("count(CASE WHEN lower(location) = 'x' THEN 1 END) AS X_loc, count(CASE WHEN lower(location) != 'x' THEN 1 END) AS Non_X_loc").group("lower(location)")
Person Load (0.9ms) SELECT count(CASE WHEN lower(location) = 'x' THEN 1 END) AS X_loc, count(CASE WHEN lower(location) != 'x' THEN 1 END) AS Non_X_loc FROM "people" GROUP BY lower(location)
=> [#<Person:0x007fd85b150f78 id: nil>, #<Person:0x007fd85b150230 id: nil>]
[6] pry(main)> p.map { |rec| rec.attributes.except('id') }
=> [{"x_loc"=>0, "non_x_loc"=>1}, {"x_loc"=>2, "non_x_loc"=>0}]
SQL
app_development=# select CASE WHEN lower(location) = 'x' THEN COUNT(id) ELSE 0 END AS X_loc, CASE WHEN lower(location) != 'x' THEN COUNT(id) ELSE 0 END AS Non_X_loc from people group by lower(location);
x_loc | non_x_loc
-------+-----------
0 | 1
2 | 0
(2 rows)
app_development=# select count(CASE WHEN lower(location) = 'x' THEN 1 END) AS X_loc, count(CASE WHEN lower(location) != 'x' THEN 1 END) AS Non_X_loc from people group by lower(location);
x_loc | non_x_loc
-------+-----------
0 | 1
2 | 0
(2 rows)
Update- II
The classical approach to get the output same as FILTER :
app_development=# select count(CASE WHEN lower(location) = 'x' THEN 1 END) AS X_loc, sum(CASE WHEN lower(location) != 'x' THEN 1 END) AS Non_X_loc from people;
x_loc | non_x_loc
-------+-----------
2 | 1
(1 row)
app_development=# select sum(CASE WHEN lower(location) = 'x' THEN 1 END) AS X_loc, sum(CASE WHEN lower(location) != 'x' THEN 1 END) AS Non_X_loc from people;
x_loc | non_x_loc
-------+-----------
2 | 1
(1 row)
app_development=# select id, location, name from people;
id | location | name
----+----------+------
2 | X | foo
3 | X | foo
4 | Y | foo
(3 rows)
app_development=#
And In Rails way :-
Loading development environment (Rails 4.2.0)
[1] pry(main)> p = Person.select("sum(CASE WHEN lower(location) = 'x' THEN 1 END) AS X_loc, sum(CASE WHEN lower(location) != 'x' THEN 1 END) AS Non_X_loc")
Person Load (0.6ms) SELECT sum(CASE WHEN lower(location) = 'x' THEN 1 END) AS X_loc, sum(CASE WHEN lower(location) != 'x' THEN 1 END) AS Non_X_loc FROM "people"
=> [#<Person:0x007fd85b6e6a78 id: nil>]
[2] pry(main)> p.first.attributes.except("id")
=> {"x_loc"=>2, "non_x_loc"=>1}
[3] pry(main)> p = Person.select("count(CASE WHEN lower(location) = 'x' THEN 1 END) AS X_loc, count(CASE WHEN lower(location) != 'x' THEN 1 END) AS Non_X_loc")
Person Load (0.5ms) SELECT count(CASE WHEN lower(location) = 'x' THEN 1 END) AS X_loc, count(CASE WHEN lower(location) != 'x' THEN 1 END) AS Non_X_loc FROM "people"
=> [#<Person:0x007fd85b77f098 id: nil>]
[4] pry(main)> p.first.attributes.except("id")
=> {"x_loc"=>2, "non_x_loc"=>1}
[5] pry(main)>
Honestly, what you have works fine, you just need to understand that if there's no value in the hash for true (or for false for that matter) then the value must default to zero, you can do that with .to_i on what will be a nil value. So, eg.:
ny_count = User.group("lower(localidade) = 'new york'").count
"New York: #{ny_count[true].to_i}
Not New York: #{ny_count[false].to_i}
"

Outer join operator not allowed with OR in my WHERE clause - Error: ORA-01719

I need to check for the conditions at the bottom, but I cannot change use OR because of the (+) that are involved. I did not set that part up, so I am not sure how to rearrange it. Can someone tell me what I could do to get those conditions to go through?
SELECT DISTINCT
t.tkt_sid,
ts.tkt_sts_dsc,
tp.prty_dsc,
a.agt_cont_nbr,
au_a.user_nm assigned_to,
t.rcd_lst_user_ts
FROM
afp_asd.tkt t,
afp_asd.tkt_prty tp,
afp_asd.tkt_sts ts,
afp_asd.tkt_type tt,
afp_asd.tkt_log tl,
afp_asd.agt a,
afp_asd.asd_user au_a,
afp_asd.asd_user au_c,
afp_asd.asd_user au_l,
afp_asd.asd_user au_log,
afp_asd.prb_area pa1,
afp_asd.prb_area pa2,
afp_asd.prb_area pa3,
afp_asd.mktg_org mo,
afp_asd.src_sys ss,
afp_asd.agt ofc,
afp_asd.co c,
afp_asd.agt_sts ast
WHERE (
t.prty_cd = tp.prty_cd
AND t.tkt_sts_cd = ts.tkt_sts_cd
AND t.tkt_type_cd = tt.tkt_type_cd
AND t.agt_sid = a.agt_sid
AND t.assigned_id = au_a.asd_user_id
AND t.rcd_crt_user_id = au_c.asd_user_id (+)
AND t.lst_updater_id = au_l.asd_user_id
AND t.tkt_sid = tl.tkt_sid
AND t.prb_area_sid = pa3.prb_area_sid
AND tl.rcd_crt_user_id = au_log.asd_user_id
AND pa3.prb_hier_sid = pa2.prb_area_sid (+)
AND pa2.prb_hier_sid = pa1.prb_area_sid (+)
AND a.mktg_org_cd = mo.mktg_org_cd
AND a.src_sys_cd = mo.src_sys_cd
AND a.src_sys_cd = ss.src_sys_cd
AND a.ofc_id = ofc.agt_cont_nbr (+)
AND a.src_sys_cd = ofc.src_sys_cd (+)
AND a.co_sid = c.co_sid (+)
AND a.agt_sts_cd = ast.agt_sts_cd
AND tl.rcd_lst_user_ts >= :b_start_date
AND t.user_grp_sid = :b_group_id
)
AND (
(TKT_STS_DSC NOT LIKE 'Completed')
OR (
tp.prty_dsc = 'High'
AND ts.tkt_sts_dsc = 'Pending'
AND t.rcd_lst_user_ts < SYSDATE- 2
)
OR (
t.rcd_lst_user_ts < SYSDATE- 3
AND ts.tkt_sts_dsc = 'In Progress'
AND tp.prty_dsc = 'High'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 15
AND ts.tkt_sts_dsc = 'In Progress'
AND tp.prty_dsc = 'Medium'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 28
AND ts.tkt_sts_dsc = 'In Progress'
AND tp.prty_dsc = 'Low'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 7
AND ts.tkt_sts_dsc = 'Pending'
AND tp.prty_dsc = 'High'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 21
AND ts.tkt_sts_dsc = 'Pending'
AND tp.prty_dsc = 'Medium'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 43
AND ts.tkt_sts_dsc = 'Pending'
AND tp.prty_dsc = 'Low'
)
)
ORDER BY ASSIGNED_TO,
PRTY_DSC
Don't use the old FROM TableA,TableB WHERE ... join syntax. Just don't.
Instead, write out your joins individually:
FROM TableA
INNER JOIN TableB ON ...
LEFT JOIN TableC ON ...
This isn't just a general rant against the old syntax: using the new (I say "new", but it's more than 20 years old now), standard syntax will fix your problem in this case.

Using Multiple ANDs and ORs in ANSI SQL

I have a simple SQL query:
SELECT
w.fizz
FROM
widgets w
WHERE
w.special_id = 2394
AND w.buzz IS NOT NULL
AND w.foo = 12
In pseudo-code, this WHERE clause could be thought of as:
if(specialId == 2394 && buzz != null && foo == 12)
I now want to change this query so that it returns all widgets whose special_id is 2394, and whose buzz is not null, and whose foo is 12, OR whose special_id is 2394, and whose blah is 'YES', and whose num is 4. In pseudo-code:
if(specialId == 2394 && (buzz != null && foo == 12) || (blah == "YES" && num == 4))
I tried the following, only to get errors:
SELECT
w.fizz
FROM
widgets w
WHERE
w.special_id = 2394
AND
(
w.buzz IS NOT NULL
AND w.foo = 12
)
OR
(
w.blah = 'YES'
AND w.num = 4
)
Any ideas? Thanks in advance!
SELECT
w.fizz
FROM
widgets w
WHERE
w.special_id = 2394
AND
(
(
w.buzz != null
AND w.foo = 12
)
OR
(
w.blah = 'YES'
AND w.num = 4
)
)
Add additional brackets surrounding "OR", because "OR" has less priority than "AND".