Show multiple rows from single row data based on column values - sql

I have a data below
ID DATE COMPLIANCE ISBREAKREDUCED ISSECONDMEALBREAKREDUCED
1208240 4/12/2015 2 1 1
How do I use it in my base query to show different rows for column ISBREAKREDUCED & ISSECONDMEALBREAKREDUCED if there values are 1.
This table join condition is based on id and date fields which is why it selects single row. How can I split this row into a multiple rows in the output?

I think you are looking for a typical UNPIVOT query.
You could do it as:
SQL> WITH DATA AS(
2 SELECT 1208240 ID, 1 ISBREAKREDUCED, 1 ISSECONDMEALBREAKREDUCED FROM dual UNION ALL
3 SELECT 1208241 ID, 2 ISBREAKREDUCED, 3 ISSECONDMEALBREAKREDUCED FROM dual
4 )
5 SELECT *
6 FROM
7 (SELECT *
8 FROM DATA UNPIVOT (ISSECONDMEALBREAKREDUCED FOR ISBREAKREDUCED IN (ISBREAKREDUCED AS 1, ISSECONDMEALBREAKREDUCED AS 1))
9 )
10 WHERE ISBREAKREDUCED =1
11 AND ISSECONDMEALBREAKREDUCED =1
12 /
ID ISBREAKREDUCED ISSECONDMEALBREAKREDUCED
---------- -------------- ------------------------
1208240 1 1
1208240 1 1
SQL>

Related

Oracle SQL to Update rows in repeating pattern

How to update rows with a given repeating number sequence.
my table is as follows
line_type
line_val
line_pattern
A
1
null
A
2
null
B
5
null
B
6
null
C
3
null
C
4
null
Now I want to update the column value with the repeating pattern of 8532
So the table after the update will look like
line_type
line_val
line_pattern
A
1
8
A
2
5
B
5
3
B
6
2
C
3
8
C
4
5
How can I achieve this in a update statement ?
With the data you have provided it is not possible to satisfy your requirement. The data in a table is not stored in a specific order. If you want the order to be guaranteed in a select statement, you need to provide an ORDER BY clause.
In the code below there is an additional column "ORDER_BY" to specify the order in which the records need to be processed. The repeating pattern is calculated using the MOD function to convert the row number to a repeating sequence of 4 numbers and then CASE maps each of those numbers to its respective pattern location.
WITH test_data (order_by, line_type, line_val)
AS
(
SELECT 1, 'A',1 FROM DUAL UNION ALL
SELECT 2, 'A',2 FROM DUAL UNION ALL
SELECT 3, 'B',5 FROM DUAL UNION ALL
SELECT 4, 'B',6 FROM DUAL UNION ALL
SELECT 5, 'C',3 FROM DUAL UNION ALL
SELECT 6, 'C',4 FROM DUAL
)
SELECT
CASE MOD(ROW_NUMBER() OVER (ORDER BY order_by),4)
WHEN 1 THEN 8
WHEN 2 THEN 5
WHEN 3 THEN 3
WHEN 0 THEN 2
END as line_pattern,
t.*
FROM
test_data t
LINE_PATTERN ORDER_BY L LINE_VAL
------------ ---------- - ----------
8 1 A 1
5 2 A 2
3 3 B 5
2 4 B 6
8 5 C 3
5 6 C 4
If you don't care about the order then use this form:
UPDATE mytable
SET line_pattern =
CASE MOD (ROWNUM, 4)
WHEN 1 THEN 8
WHEN 2 THEN 5
WHEN 3 THEN 3
WHEN 0 THEN 2
END

How to use distinct and sum both together in oracle?

For example my table contains the following data:
ID price
-------------
1 10
1 10
1 20
2 20
2 20
3 30
3 30
4 5
4 5
4 15
So given the example above,
ID price
-------------
1 30
2 20
3 30
4 20
-----------
ID 100
How to write query in oracle? first sum(distinct price) group by id then sum(all price).
I would be very careful with a data structure like this. First, check that all ids have exactly one price:
select id
from table t
group by id
having count(distinct price) > 1;
I think the safest method is to extract a particular price for each id (say the maximum) and then do the aggregation:
select sum(price)
from (select id, max(price) as price
from table t
group by id
) t;
Then, go fix your data so you don't have a repeated additive dimension. There should be a table with one row per id and price (or perhaps with duplicates but controlled by effective and end dates).
The data is messed up; you should not assume that the price is the same on all rows for a given id. You need to check that every time you use the fields, until you fix the data.
first sum(distinct price) group by id then sum(all price)
Looking at your desired output, it seems you also need the final sum(similar to ROLLUP), however, ROLLUP won't directly work in your case.
If you want to format your output in exactly the way you have posted your desired output, i.e. with a header for the last row of total sum, then you could set the PAGESIZE in SQL*Plus.
Using UNION ALL
For example,
SQL> set pagesize 7
SQL> WITH DATA AS(
2 SELECT ID, SUM(DISTINCT price) AS price
3 FROM t
4 GROUP BY id
5 )
6 SELECT to_char(ID) id, price FROM DATA
7 UNION ALL
8 SELECT 'ID' id, sum(price) FROM DATA
9 ORDER BY ID
10 /
ID PRICE
--- ----------
1 30
2 20
3 30
4 20
ID PRICE
--- ----------
ID 100
SQL>
So, you have an additional row in the end with the total SUM of price.
Using ROLLUP
Alternatively, you could use ROLLUP to get the total sum as follows:
SQL> set pagesize 7
SQL> WITH DATA AS
2 ( SELECT ID, SUM(DISTINCT price) AS price FROM t GROUP BY id
3 )
4 SELECT ID, SUM(price) price
5 FROM DATA
6 GROUP BY ROLLUP(id);
ID PRICE
---------- ----------
1 30
2 20
3 30
4 20
ID PRICE
---------- ----------
100
SQL>
First do the DISTINCT and then a ROLLUP
SELECT ID, SUM(price) -- sum of the distinct prices
FROM
(
SELECT DISTINCT ID, price -- distinct prices per ID
FROM tab
) dt
GROUP BY ROLLUP(ID) -- two levels of aggregation, per ID and total sum
SELECT ID,SUM(price) as price
FROM
(SELECT ID,price
FROM TableName
GROUP BY ID,price) as T
GROUP BY ID
Explanation:
The inner query will select different prices for each ids.
i.e.,
ID price
-------------
1 10
1 20
2 20
3 30
4 5
4 15
Then the outer query will select SUM of those prices for each id.
Final Result :
ID price
----------
1 30
2 20
3 30
4 20
Result in SQL Fiddle.
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE MYTABLE ( ID, price ) AS
SELECT 1, 10 FROM DUAL
UNION ALL SELECT 1, 10 FROM DUAL
UNION ALL SELECT 1, 20 FROM DUAL
UNION ALL SELECT 2, 20 FROM DUAL
UNION ALL SELECT 2, 20 FROM DUAL
UNION ALL SELECT 3, 30 FROM DUAL
UNION ALL SELECT 3, 30 FROM DUAL
UNION ALL SELECT 4, 5 FROM DUAL
UNION ALL SELECT 4, 5 FROM DUAL
UNION ALL SELECT 4, 15 FROM DUAL;
Query 1:
SELECT COALESCE( TO_CHAR(ID), 'ID' ) AS ID,
SUM( PRICE ) AS PRICE
FROM ( SELECT DISTINCT ID, PRICE FROM MYTABLE )
GROUP BY ROLLUP ( ID )
ORDER BY ID
Results:
| ID | PRICE |
|----|-------|
| 1 | 30 |
| 2 | 20 |
| 3 | 30 |
| 4 | 20 |
| ID | 100 |

fetch record as in order passed for IN condition in oracle

I want to fetch the records in order passed for IN condition.
select * from table where id in(6,3,7,1);
is returning the rows as
id name
1 abc
3 xy
6 ab
7 ac
but I want to display the records in same orders as ids passed in condition in Oracle
id name
6 ab
3 xy
7 ac
1 abc
Please help me in fetching the records in same order as in condition ids in oracle. The values in IN condition may change dynamically.
You can do this with a case statement in the order by clause or using a join.
select *
from table
where id in(6,3,7,1)
order by (case id when 6 then 1 when 3 then 2 when 7 then 3 when 1 then 4 end);
Or:
with ids as (
select 6 as id, 1 as ordering from dual union all
select 3 as id, 2 as ordering from dual union all
select 7 as id, 3 as ordering from dual union all
select 1 as id, 4 as ordering from dual
)
select *
from table t join
ids
on t.ids = ids.id
order by ids.ordering;
Note that you don't need the in in this case, because the join does the filtering.
you can use trick
select * from table where id in(6,3,7,1) order by case when id = 6 then 1
id = 3 then 2
id = 7 then 3
id = 1 then 4
end

Ms sql server , select query show overhand?

i want get query from 2 table but show all column overhand
first all column from table 1 Second all column from table 2 then show overhand
table1
----------
a 1 2 3
table2
----------
b 4 5 6
query Result
----------
a 1 2 3
b 4 5 6
Grateful
do you mean:
Select * from table1
Union
Select * from table2
if you want all data no matter they are repetitive or not use UNION ALL otherwise if you want to have unique result use UNION
for example if you had 1 2 3 in table2 the result with UNION will be
1 2 3
and result with UNION ALL will be
1 2 3
1 2 3
Try using UNION in your query:
select * from table1
union all
select * from table2

Get next row value based on returned list of rows

In Oracle, suppose I have a query that returns the following list:
ID Sequence#
12 1
15 3
25 5
All I know in this case is the ID of some row (let's suppose 12), I need to return the ID of a row with the next sequence number which in this case is 3 (id = 15)
How can I do it? I know there's a Oracle function lead, but I wasn't able to successfully impement is.
Yes, you can use lead function to get the next value. Here is an example of how it can be done.
-- sample of data from your question
SQL> with t1(ID, Sequence#) as
2 (
3 select 12, 1 from dual union all
4 select 15, 3 from dual union all
5 select 25, 5 from dual
6 )
7 select *
8 from (select id
9 , sequence#
10 , lead(sequence#) over(order by id) next_sequence#
11 , lead(id) over(order by id) next_id#
12 from t1
13 )
14 where id = 12
15 ;
ID SEQUENCE# NEXT_SEQUENCE# NEXT_ID#
---------- ---------- -------------- ----------
12 1 3 15
SELECT * FROM table1 where ID in (SELECT min(ID) FROM table1 WHERE ID > 12)
Select sequence from my_ table where id=(select min(id) from my_table where sequence> 1)
Replace (1) in the above query with any value that you are searching for its next