Region wise percentage - oracle

i need to calculate percentage grosssales with regionwise breakup on a particular segment ie Domestic Corp .
My Query is
select REGION_NAME,
round(ratio_to_report(nvl(sum(gross_sales_amt_t),0)) over ()*100) as Gr_Sales_domcorp
from fact_mfdex_segment A
JOIN dim_location B
ON a.branch_code = b.branch_code
WHERE to_date(DATE_SK,'YYYYMMDD') between '01-feb-2016' and '01-mar-2016'
AND week_flag='Y'
AND a.segments = 'Domestic Corp.'
group by REGION_NAME;
I need to repeat the same query for HNI,RETAIL ETC. instead of Domestic Corp. rather than writing different query can i use my first query to add other segments. I have tried case statement but not working. Any help appreciated

Just include all the records for required segments by putting them inside "IN" clause and then group by segment also and here you go for expected results.
select REGION_NAME,
round(ratio_to_report(nvl(sum(gross_sales_amt_t),0)) over ()*100) as Gr_Sales_domcorp
from fact_mfdex_segment A
JOIN dim_location B
ON a.branch_code = b.branch_code
WHERE to_date(DATE_SK,'YYYYMMDD') between '01-feb-2016' and '01-mar-2016'
AND week_flag='Y'
AND a.segments IN ( 'Domestic Corp.','HNI','RETAIL')
group by REGION_NAME, a.segments;

Add a.segments to the selected columns, remove the "AND a.segments = ..." line, partition ratio_to_report by a.segments, and group by a.segments and REGION_NAME. You may want to change the output column name from Gr_Sales_domcorp to Gr_Sales. Something like this:
select REGION_NAME, a.segments,
round(ratio_to_report(nvl(sum(gross_sales_amt_t),0))
over (partition by a.segments)*100) as Gr_Sales
from fact_mfdex_segment A
JOIN dim_location B
ON a.branch_code = b.branch_code
WHERE to_date(DATE_SK,'YYYYMMDD') between '01-feb-2016' and '01-mar-2016'
AND week_flag='Y'
group by a.segments, REGION_NAME
order by a.segments, REGION_NAME

Related

How to use GROUP BY clause with COUNT(*)

I have two tables on Oracle database, one is named departments_table and the other is locations_table. The departments.table has dep_id, dep_name, location_id, staff_id, employer_id. The locations table consists of location_id, city_id, streetname_id and postcode_id. How do I calculate the number of departments that each location has?
This is the code below is what I have tried to replicate but have been unsuccessful. The error message below that is what shows once the code has submitted.
SELECT dep_name, location_id,
COUNT(*)
FROM departments_table
WHERE location_id => 1
GROUP BY dep_name;
The results of this is an error, " not a single group function "
If you want to count how many departments are in each location, then you must group by location, not by department name, right? Let's start with that.
Then, you don't need ANYTHING about the individual departments in the output of the query, do you? You just need the location id and the count of departments.
select location_id, count(*) as cnt
from departments_table
group by location_id
;
This does most of the work. You may want to add the location name (city, address, etc.), which is/are stored elsewhere - in the locations_table. So you will need a join. And there may be locations in that table that are not, in fact, the location of any department (their id doesn't appear in the departments_table at all). If so, you would need an OUTER join. Also for those departments you probably want to show a count of 0 (rather than null) - you can "fix" that with the nvl() function. So you will end up with something like
select l.*, nvl(g.cnt, 0) as department_count
from locations_table l
left outer join
( select location_id, count(*) as cnt
from departments_table
group by location_id
) g
on l.location_id = g.location_id
;
SELECT l.location_id, l.city, COUNT(d.DEPARTMENT_ID)
FROM OEHR_LOCATIONS l, OEHR_DEPARTMENTS d WHERE l.location_id = d.location_id
GROUP BY l.location_id, l.city ORDER BY l.city;
This method works. I created aliases and made minor changes. OEHR stands for the table names so ignore that.

ORA-00904: invalid column name but I am using the correct column name

Can someone see where I am going wrong in the below query? I am getting the error message that the GROUP BY column doesn't exist, but it clearly does as I see that column name in the output when I don't use the GROUP BY.
SELECT
(SELECT customer_address.post_code FROM customer_address WHERE customer_address.address_type = 0 AND customer_address.customer_no = orders.customer_no) postcode, SUM(orders.order_no) orders
FROM
orders, customer_address
WHERE
orders.delivery_date = '27-MAY-15'
GROUP BY
postcode;
The answer is: You cannot use an alias name in GROUP BY.
So:
GROUP BY (SELECT customer_address.post_code ...);
Or:
select postcode, sum(order_no)
from
(
SELECT
(SELECT customer_address.post_code FROM customer_address WHERE customer_address.address_type = 0 AND customer_address.customer_no = orders.customer_no) postcode,
orders.order_no
FROM orders, customer_address
WHERE orders.delivery_date = '27-MAY-15'
)
GROUP BY postcode;
EDIT:
However, your query seems wrong. Why do you cross-join orders and customer_address? By mistake I guess. Use explicit joins (INNER JOIN customer_address ON ...), when using joins to avoid such errors. But here I guess you'd just have to remove , customer_address.
Then why do you add order numbers? That doesn't seem to make sense.

Hibernate HQL GroupBy in Oracle

I created this query using HQL with Hibernate and Oracle
select c from Cat c
left join c.kittens k
where (c.location= 1 OR c.location = 2)
and (i.activo = 1)
group
by c.id,
c.name,
c.fulldescription,
c.kittens
order by count(e) desc
The problem comes with the fact that in HQL you need to specify all fields in Cat in order to perform a Group By, but fulldescription is a CLOB, and you cannot group by by a CLOB (I get a "Not a Group By Expression" error. I've seen a few solutions around for a pure SQL sentence but none for HQL.
A serious issue GROUP BY of HQL because if you specify your object in GROUP BY and in your SELECT field list behaviours are differents. In GROUP BY has considered only id field but in SELECT field list all fields are considered.
So you can use a subquery with GROUP BY to return only id from your object, so that result becomes an input for the main query, like the follow I write for you.
Pay attention there are some alias table (i and e) not defined, so this query doesn't work, but you know as fixed.
Try this:
select c2 from Cat c2
where c2.id in (
select c.id from Cat c
left join c.kittens k
where (c.location= 1 OR c.location = 2)
and (i.activo = 1) <-- who is i alias??
group by c.id)
order by count(e) desc <-- who is e alias???

Best way to exclude records from multiple tables

I got the following tables (just an example): vehicles, vehicle_descriptions, vehicle_parts
vehicles have 1 to many with vehicle_descriptions and vehicle_parts. There may not be a corresponding vehicle_description/part for a given vehicle.
SELECT * FROM vehicles
LEFT OUTER JOIN vehicles d ON vehicles.vin = d.vin AND d.summary NOT LIKE 'honda'
LEFT OUTER JOIN
(SELECT SUM(desc_total) FROM vehicle_descriptions WHERE NOT LIKE desc 'honda' GROUP BY vin) b
ON vehicles.vin = vehicle_b.vin
LEFT OUTER JOIN
(SELECT SUM(part_count) FROM vehicle_parts WHERE part_for NOT LIKE 'honda' GROUP BY vin) c ON vehicles.vin = c.vin
If either vehicle_desc, vehicles, or part contains the exclusion term, the whole record should not show up in the result set. The query above will return a record even if one of the tables contain the exclusion term Honda. How would I fix the above query?
You're not using any of the information in either sum() as part of what you show, just to decide whether to include the vehicle. And you're doing an unnecessary self join in your first clause. Generally in situations like this, the "exists" and "not exists" clauses work well. So what about this? I'll use Oracle syntax, you can convert to ANSI of course.
SELECT * FROM vehicles v where summary <> 'honda'
and not exists (select 1 from vehicle_descriptions d where d.vin = v.vin and d.desc <> 'honda')
and not exists (select 1 from vehicle_parts p where p.vin = v.vin and p.part_for <> 'honda')

need help on sql query

am a newbie to Oracle/PL SQL.I've 2 tables A and B.
A has a column CustId,Age,Location and Date. Table B has 2 columns CustId,CustName.
What would be the sql query to show show CustName and Location for a given age?
Thanks.
your question "What would be the sql query to show show CustName and Location for a given age?" helps define your query pretty well:
SELECT CustName, Location
FROM TableA a
INNER JOIN TableB b
ON b.CustId = a.CustId
WHERE a.Age = #
All we need to do on top of that select for your specific fields is make sure to join the two tables on their common column (CustID).
Another option would be to avoid the WHERE statement:
SELECT CustName, Location
FROM TableB b
INNER JOIN TableA a
ON a.CustID = b.CustID
AND a.Age = #
you need join. something like
SELECT custname, location FROM a JOIN b ON a.custid = b.custid WHERE age = [age];

Resources