Orcale - Missing Right Paranthesis - oracle

I am trying to run an oracle query using, Case when and Sum together, It gives me an error saying I am missing the right paranthesis.
The query below,
SELECT c.Customer_name,
CASE WHEN SUM(status = 'DELIVERED') = count(*) THEN 'A'
WHEN SUM(status = 'DELIVERED') > 0 THEN 'B'
WHEN SUM(status = 'SUBMITTED') > 0 THEN 'C'
ELSE 'No Match'
END AS Match
FROM Customer_Order c
group by c.Customer_name order by c.Customer_name;
Changed my query to look like this and it says, I am missing keyword
SELECT c.Customer_name,
CASE WHEN SUM(c.status) = 'DELIVERED' = (count(c.status)) THEN 'A'
WHEN SUM(c.status) = 'DELIVERED' > 0 THEN 'B'
WHEN SUM(c.status) = 'SUBMITTED' > 0 THEN 'C'
ELSE 'No Match'
END AS Match
FROM Customer_Order c
group by c.Customer_name order by c.Customer_name;

Ok, what I think you are trying to do includes counting all the cases where status = 'DELIVERED' and status = 'SUBMITTED' and then comparing those with something to determine what the outcome is. But you can't sum a conditional expression like status = 'DELIVERED' so you need to do it in two steps: one to make a number out of the conditional and one to compare the sum with something.
Step 1: To count the cases where status = 'DELIVERED' you need a column that is 1 when the status is DELIVERED and 0 when it is not (and the same with 'SUBMITTED'). That way you have numbers to sum. So the data we want to run your query on is:
SELECT *,
CASE WHEN status = 'SUBMITTED' THEN 1 ELSE 0 END AS Is_submitted,
CASE WHEN status = 'DELIVERED' THEN 1 ELSE 0 END AS Is_delivered
FROM Customer_order
Step 2: Now we can use your query on the results of Step 1:
SELECT
c.Customer_name,
CASE WHEN SUM(c.delivered) = count(*) THEN 'A'
WHEN SUM(c.delivered) > 0 THEN 'B'
WHEN SUM(c.submitted) > 0 THEN 'C'
ELSE 'No Match'
END AS X
FROM (the query above) as c
GROUP BY c.Customer_name
ORDER BY c.Customer_name;
Substituting Step 1 into Step 2 we get the actual query:
SELECT
c.Customer_name,
-- SUM(c.Is_delivered),
-- SUM(c.Is_submitted),
-- count(*),
CASE WHEN SUM(c.delivered) = count(*) THEN 'A'
WHEN SUM(c.delivered) > 0 THEN 'B'
WHEN SUM(c.submitted) > 0 THEN 'C'
ELSE 'No Match'
END AS X
FROM (
SELECT *,
CASE WHEN status = 'SUBMITTED' THEN 1 ELSE 0 END AS submitted,
CASE WHEN status = 'DELIVERED' THEN 1 ELSE 0 END AS delivered
FROM Customer_order
) as c
GROUP BY c.Customer_name
ORDER BY c.Customer_name;
Try it here:
https://www.db-fiddle.com/f/mSdREEgU1mT1pvczG2kZgm/1

You appear to be trying to count true comparions; unlike some other languages, in SQL a true value is not the same as 1 and a false value is not 0 so you need to use a CASE expression to convert the comparison to something that can be summed (or counted).
In this case, you can use conditional aggregation:
SELECT Customer_name,
CASE
WHEN COUNT(CASE status WHEN 'DELIVERED' THEN 1 END) = COUNT(status)
THEN 'A'
WHEN COUNT(CASE status WHEN 'DELIVERED' THEN 1 END) > 0
THEN 'B'
WHEN COUNT(CASE status WHEN 'SUBMITTED' THEN 1 END) > 0
THEN 'C'
ELSE 'No Match'
END AS Match
FROM Customer_Order
group by Customer_name
order by Customer_name;

Related

Problem using multiple CASE in WHERE clause

I'm trying to create an SQL that added two more conditions when the specific column(value) is matched.
Example:
SELECT
COLUMN_NAME
FROM
TABLE
WHERE
NAME_COLUMN = 'NAME'
AND
CASE
WHEN AGE = '18'
THEN ADULTHOOLD_COLUMN
END = 1
AND
CASE
WHEN AGE = '18'
THEN ADULTHOOLD_COLUMN_1
END = 1
It is working when AGE = 18 it will return value that ADULTHOOLD_COLUMN = 1 and ADULTHOOLD_COLUMN_1 = 1
but when age is not equal to 18 it will not return any rows.
I was expecting that all of the data(with 1 or 0) will return.
ADULTHOOLD_COLUMN(Value in db is 1 or 0)
ADULTHOOLD_COLUMN_1(Value in db is 1 or 0)
Sounds a bit strange, but ok, looks like you need else:
SELECT
COLUMN_NAME
FROM
TABLE
WHERE
NAME_COLUMN = 'NAME'
AND
CASE
WHEN AGE = '18'
THEN ADULTHOOD_COLUMN
ELSE 1
END = 1
AND
CASE
WHEN AGE = '18'
THEN ADULTHOOD_COLUMN_1
ELSE 1
END = 1
Or maybe just to make it more readable:
SELECT
COLUMN_NAME
FROM
TABLE
WHERE
NAME_COLUMN = 'NAME'
AND (AGE is null OR AGE!='18' OR AGE = '18' AND ADULTHOOD_COLUMN = 1)
AND (AGE is null OR AGE!='18' OR AGE = '18' AND ADULTHOOD_COLUMN_1 = 1)
PS. Are you sure that AGE is not number? If that's a number datatype, you need to replace '18' to 18

how to select all on laravel query builder?

(1)
DB::query()
->select(*) <----how to write it's error
->addSelect(DB::raw('SUM(CASE WHEN B.approve IS NULL THEN 0 ELSE 1 END) as Ashowcount'))
->addSelect(DB::raw('SUM(B.approve) as Yshow'))
->from(a16 as A)
.....
(2)
DB::table(a16 as A')
->Select(DB::raw('SUM(CASE WHEN B.approve IS NULL THEN 0 ELSE 1 END) as Ashowcount'))
->addSelect(DB::raw('SUM(B.approve) as Yshow'))
...... <---just select two column
I want to ask how can I select all from a16 with above two query code?
I need use addselect to add the DB:raw code
I only can type one by one just like
->select('A.id','A.s_main','A.s_brand','A.s_model','A.s_price','A.s_count','A.s_unit','A.s_location','A.s_geography','A.s_location','A.u_id','A.classify','A.s_boss','A.route','A.created_at')
I feel it's some no efficiency.
How can I select all column easily?
DB::query()
->select('A.*')
->addSelect(DB::raw('SUM(CASE WHEN B.approve IS NULL THEN 0 ELSE 1 END) as Ashowcount'))
->addSelect(DB::raw('SUM(B.approve) as Yshow'))
->from(a16 as A)

postgres inner join sum for when no relation exists

I am trying to run a simple query where I get a sum of gardeners who have zero support visits. I would like to add other cases, but first I would like to get this zero thing right. This is what I have come up with:
Gardener.from(Gardener.joins(:support_visits).group(:gardener_id).select("CASE WHEN count(gardener_id) = 0 THEN 1 END AS zero_count"),:t).select("sum(t.zero_count) as tot_zero_count")
Which gives me the following sql query:
SELECT sum(t.zero_count) as tot_zero_count
FROM
(
SELECT CASE WHEN count(gardener_id) = 0 THEN 1 END AS zero_count
FROM "gardeners" INNER JOIN "support_visits"
ON "support_visits"."gardener_id" = "gardeners"."id"
GROUP BY gardener_id
) t
The query runs but gives me nil.
Your current query uses count(gardener_id) = 0 which is never true because any group will have at least one record. Instead, you can LEFT JOIN the gardeners table to the support_visits table. Any gardener which does not appear in the support_visits table will not match to a visit, leaving a null value which you can then count.
SELECT SUM(CASE WHEN "support_visits"."gardener_id" IS NULL THEN 1 ELSE 0 END) AS zero_count
FROM "gardeners" LEFT JOIN "support_visits"
ON "support_visits"."gardener_id" = "gardeners"."id"
Here is the Ruby ActiveRecord code for this query:
Gardener.from(Gardener.joins("LEFT JOIN `support_visits` ON gardeners.id = support_visits.gardener_id").select("SUM(CASE WHEN "support_visits"."gardener_id" IS NULL THEN 1 ELSE 0 END) AS zero_count"))

PL/SQL : Example for select and update the record based on certain rule

I have situation something like below...
select * from tableA A
if A.salary > 100 and A.years > 0 then
update tableA set A.level = '1' where A.id = id;
else if A.salary > 200 A.years > 1 then
update tableA set A.level = '2' where A.id = id;
else
update tableA set A.level = '0' where A.id = id;
end if
how i can implement this in PL/SQL? above situation is just an example.
You don't need to do this in PL/SQL; it can be done in a single UPDATE statement by using a CASE expression:
update tablea
set level = case when salary > 100 and years > 0 then 1
when salary > 200 and years > 1 then 2
else 0
end
It's worth noting that "level" is a reserved word (it's a psuedocolumn used for Oracle's hierarchical queries) and can cause problems if you use it. I'd choose something else if possible.

Return only one row from Oracle SQL, using outer join and case statement

I'm trying to figure out how to just return one row per result, even if there are multiple activities ('act's) per result. I've read and searched to no avail.
What I want:
Date Site Result act1 act2
1985-06-10 1008 NT6 5 10
What I get:
Date Site Result act1 act2
1985-06-10 1008 NT6 5
1985-06-10 1008 NT6 10
Here's my (example) code, which I know is not broken, but it's the path I tried. I just don't know how to obtain what I want.
SELECT
t."Date",
t."Site",
t."Result",
CASE
WHEN a.Type = 'act1'
THEN a.Count
END AS "act1",
CASE
WHEN a.Type = 'act2'
THEN a.Count
END AS "act2"
FROM
(
SELECT Sample.SAMPLE_ID,
Sample.Date,
Sample.Site,
Sample.Result
FROM Sample
WHERE Sample.Date is Between then and now
) t
LEFT OUTER JOIN
ACTIVITY
ON (ACTIVITY.SAMPLE_ID = t.SAMPLE_ID)
here you go
select t."Date", t."Site", t."Result",
sum(case when a.Type = 'act1' then a.Count else 0 end ) AS act1,
sum(case when a.Type = 'act2' then a.Count else 0 end ) AS act2
from sample left outer join activity
on (activity.sample_id = t.sample_id)
where sample.date is between then and now
and don't use braces on column names.

Resources