Expand Grouped Rows within a Group By Query - oracle11g

I'm curious if there is a way within Oracle SQL Developer to expand the rows contained within a Group By Query whether in a report or just in the data grid. For example, let's say I have a single Payment Transaction with a payment amount. I have grouped these fields and I have the SUM of the items which is the total payment amount. It would be very nice if I there was a feature that would allow me to view the items within the transaction that make up the total payment amount without having to remove the Group By fields and the Aggregate SUM function.
Using the data below as an example to show what I am looking for. Only two tables in the below sample data. pymt_transactions and transaction_items.
WITH pymt_transactions AS
(
SELECT 1 AS tran_id FROM dual UNION
SELECT 2 AS tran_id FROM dual UNION
SELECT 3 AS tran_id FROM dual UNION
SELECT 4 AS tran_id FROM dual UNION
SELECT 5 AS tran_id FROM dual
) /* END pymt_transactions CTE */
--SELECT * FROM pymt_transactions;
, transaction_items AS
(
SELECT 1 AS tran_id, 'T-Shirt' AS retail_item, 15 AS amt FROM dual UNION
SELECT 1 AS tran_id, 'Shoes' AS retail_item, 50 AS amt FROM dual UNION
SELECT 1 AS tran_id, 'Pants' AS retail_item, 40 AS amt FROM dual UNION
SELECT 1 AS tran_id, 'Comb' AS retail_item, 3 AS amt FROM dual UNION
SELECT 2 AS tran_id, 'Sweater' AS retail_item, 15 AS amt FROM dual UNION
SELECT 2 AS tran_id, 'Belt' AS retail_item, 12 AS amt FROM dual UNION
SELECT 2 AS tran_id, 'Pants' AS retail_item, 40 AS amt FROM dual UNION
SELECT 2 AS tran_id, 'Watch' AS retail_item, 23 AS amt FROM dual
) /* END transaction_items CTE */
SELECT pt.tran_id, ti.retail_item, ti.amt
FROM pymt_transactions pt
LEFT JOIN transaction_items ti ON ti.tran_id = pt.tran_id
ORDER BY pt.tran_id
;
The above produces the below result set.
Now for the Grouped By version. Using the same two CTE's in the above example:
SELECT pt.tran_id, COUNT(ti.retail_item) AS num_retail_items,
NVL(SUM(ti.amt),0) AS payment_amount
FROM pymt_transactions pt
LEFT JOIN transaction_items ti ON ti.tran_id = pt.tran_id
GROUP BY pt.tran_id
ORDER BY pt.tran_id
;
The above Grouped By Query produces the below results and groups by tran_id:
Again, without my having to write two different queries is there a way I can simply have a Group By query and provide the ability to just click to expand in order to view the retail_items? I've used reports and other systems that have this feature. In both transaction 1 and transaction 2 there are four Retail Items. I want to view these items without having to remove the Group By Clause and the Aggregate SUM Function that is producing the total in the payment_amount column.

Try building a report.
View > Reports.
User Defined Reports.
Add a new report.
Provide the main SQL, then go and add a child report, and tie the data together with a :BIND.
Then click on a row up top, and get the detail data you want below.
You can start to have fun with Charts if you'd like too.

Having access to all the values at once, maybe this can be a solution?
SELECT pt.tran_id
, ti.retail_item
, ti.amt
,COUNT(ti.retail_item) over (Partition by pt.tran_id)
,SUM(ti.amt) over (Partition by pt.tran_id)
FROM pymt_transactions pt
LEFT JOIN transaction_items ti ON ti.tran_id = pt.tran_id
ORDER BY pt.tran_id
;

Ok lets try to build a drill down report.
First build a user defind report calcualting the sum adding a filter (I beleive capital letters are important here)
Then add another report with your initial sql.
And add a reference to the sumcnt report
Now running the top report and right click it you will get this:
good luck

Related

PL SQL SELECT Case Statements involving aggregate values

I'm trying to write a query that in Teradata but I'm not sure how to do it; my table looks like this:
col1: text (account_number)
col2: text (secondary account number)
col3: text (Primary_cust)
the business requirements are:
"Group records by account number.
If there is only one record for an account then keep that record.
If there are multiple records for an account number then:
(1) if only one record has Primary_CUST = 'Y' then keep.
(2) if multiple records have Primary_CUST = 'Y' then keep one with lowest SCDRY_ACCT_NBR
(3) If no records have Primary_CUST = 'Y' then keep one with lowest SCDRY_ACCT_NBR.
I know I need a CASE statement and I'm able to write the first requirement, but not sure on the second. Any help would be greatly appreciated.
You just have to think about how to order the rows to get the row you want on top, seems to be like this:
SELECT * FROM tab
QUALIFY
Row_Number()
Over (PARTITION BY account_number -- for each account
ORDER BY Primary_CUST DESC -- 'Y' before 'N' (assuming it's a Y/N column)
,SCDRY_ACCT_NBR -- lowest number
) = 1 -- return the top row
Of course QUALIFY is proprietary Teradata syntax, if you need to do this on Oracle you have to wrap it in a Derived Table:
SELECT *
FROM
(
SELECT t.*,
Row_Number()
Over (PARTITION BY account_number -- for each account
ORDER BY Primary_CUST DESC -- 'Y' before 'N' (assuming it's a Y/N column)
,SCDRY_ACCT_NBR) AS rn-- lowest number
FROM tab
) AS dt
WHERE rn = 1 -- return the top row

COUNT and DISTINCT without group by

I've two tables. One with clients, other with products bought by clients.
When I want to get the list of all products and clients, I do:
SELECT client_name, prod_id FROM TAB_CLIENT
INNER JOIN TAB_PROD ON prod_client = client_name
So I get (eg)
Henri - Potatoes
Henri - Chocolate
Tom - Beer
Nice. Now I want to know how many different clients I have.
So I tried to use COUNT and DISTINCT. Like this:
SELECT COUNT(DISTINCT client_name) AS num_client, client_name, prod_id
FROM TAB_CLIENT
INNER JOIN TAB_PROD ON prod_client = client_name
I want to get:
2 - Henri - Potatoes
2 - Henri - Chocolate
2 - Tom - Beer
So "2" in first colum as the whole number of different clients is 2 (Henri and Tom), name of the client at second colum and name of product as third colume.
But in fact if I add the count(distinct), I get only ONE result (seems like if there was a "group by" on num_client). And I don't want to GROUP BY on client_name as in this case I'll loose the product.
Is it possible to perform that in one query, or do I have to perform one select for counting and an other to get the result?
I notice all examples given in Stack are about Count/Distinct returning only number but not the number AND results.
Thanks
PS: I'm running MariaDB.
SELECT
( SELECT COUNT(DISTINCT client_name) FROM TAB_CLIENT ) AS Number_of_clients,
client_name,
prod_id
FROM TAB_CLIENT
INNER JOIN TAB_PROD ON prod_client = client_name

find count of distinct values in a column

Hi all am trying to build a sql query to display some information on a dashboard.
I have a table in which i store my sales data.My query needs to find total sales in last 7 days,average and group it based on region(which is present in user table.) .I created a temp table to get the item sales.DashBoard_Items table contains particular item that needs to be shown on dashboard.Now my problem is i need to get the store count of each region to find average sales.Can some one please help
Declare #TableTest
table(itemid int,itemname varchar(100),itemdescription varchar(100),id int,itemidd int,userid int,orderdate varchar(40),qty int)
insert into #TableTest
select * from DashBoard_Items join
SalesQTY on SalesQTY.OrderDate>= CONVERT(varchar(10) , DATEADD(DAY,-7,GETDATE()),126)
and OOS_DashBoard_CoreItems.itemid=SalesQTY.itemid
select distinct t.userid,u.region from #TableTest t join users u on t.userid=u.userid and region is not null
above select query returns
how can i get region count from the above select query
region count
5 - SUN WEST 2
2 - LONG ISLAND 3
You need to group by region and then use cont(*)
SELECT region, count(*)
FROM #TableTest
GROUP BY region;
Please try:
SELECT
Region,
COUNT(*) AS [Count]
FROM YourTable
GROUP BY Region
OR
SELECT
DISTINCT Region,
COUNT(*) OVER (PARTITION BY Region) AS [Count]
FROM YourTable
SELECT u.region, COUNT(*)
FROM #TableTest t JOIN users u ON t.userid=u.userid AND u.region IS NOT NULL
GROUP BY u.region
try
SELECT region, count( * )
FROM mytable
GROUP BY region

SQLite Select from one table or from another

I would like to know how to make a single query to select something from one table or from another. For example I have Table A with the aID=2 and Table B with bID=3. So how to make the query to return the id from table A or table B for a given id = 3?
Thanks in advance
If you do not know which table to use before you're running the query, you can combine multiple queries with UNION, provided that you're selecting the same number of columns:
SELECT something FROM A WHERE aID = 3
UNION ALL
SELECT something FROM B WHERE bID = 3
If you do not want to duplicate the WHERE condition, you can use a nested query and apply the WHERE to its result:
SELECT something
FROM (SELECT aID as ID, something FROM A
UNION ALL
SELECT bID , something FROM B)
WHERE ID = 3

Compare (< or >) the result of one column, against the result of another column of two select statements? - Oracle

Question:
How do you compare (< or >) the result of one column, against the result of another column of two select statements?
More details:
I need to get a list only of the sold out movies. To do this, I need to check if
the number on the rented_movie_count on the first select statement is equal or greater than the number on the available_movie_count on the second select statement.
First Statement
result of the
select MOVIE_ID, count(MOVIE_ID) as rented_movies_count
from MOVIE_QUEUE
WHERE STATUS_ID=2
group by MOVIE_ID;
Second Statement
select MOVIE_ID, count(MOVIE_ID) as available_movie_count
from dvd
group by MOVIE_ID;
I am still very new to this and I am trying to learn, even suggestions about what kind of
syntax (operators, expressions, etc) should I use will help at least point me on a a directions to do more research. Thanks in advance
Given your database structure, a possible solution would be
SELECT rented.MOVIE_ID
,rented_movies_count
,available_movie_count
FROM (
SELECT MOVIE_ID, count(MOVIE_ID) AS rented_movies_count
FROM MOVIE_QUEUE
WHERE STATUS_ID=2
GROUP BY MOVIE_ID
) rented
,(SELECT MOVIE_ID, count(MOVIE_ID) AS available_movie_count
FROM dvd
GROUP BY MOVIE_ID
) available
WHERE rented.movie_id = available.movie_id
AND rented_movies_count >= available_movie_count
;
I've set up an example on http://www.sqlfiddle.com/#!4/3fc59/11 to test. But I guess that's more or less what you've come up with.
But I somewhat doubt that your database structure is really optimal!? Do you really store more than one record for a singe movie_id in the table dvd?
Wouldn't it be more useful to have exactly one record per movie_id in dvd along with some movie attributes and store the rental status of the dvds in movie_queue.status_id?
If movie_queue.status_id is defined as say
...available
...rented
Then your query would be much more easy:
SELECT MOVIE_ID
,count(case when status_id = 1 then 1 end) AS available_movie_count
,count(case when status_id = 2 then 1 end) AS rented_movies_count
FROM MOVIE_QUEUE
GROUP BY MOVIE_ID
HAVING count(case when status_id = 2 then 1 end) >= count(case when status_id = 1 then 1 end)
;
See for example http://www.sqlfiddle.com/#!4/13739/1

Resources