how to select some columns with null or empty rows - sql

I have a table with 5 columns in each row, I want to select * when status column =1 and see just date and status columns if it is not =1

I think this is better, because the union makes the query run very slow.
SELECT date,
status,
CASE WHEN status = 1 THEN asd end as asd,
CASE WHEN status = 1 THEN asd1 end as asd1,
...
FROM table

Related

Grouping by id and looking at another column in a particular order to see if the id group satisfies a particular condition

customer_id
transaction success
1
Failed
2
Complete
1
Failed
1
Complete
3
Failed
2
Failed
3
Complete
3
Failed
3
Failed
3
Complete
Essentially I want to write a statement to identify if the customer has had a completed transaction after having had a failed transaction sometime before. So in this example, customer 1 and customer 2 would be satisfy this. Assume that there is an added timestamp column next to transaction success.
The resulting table should look like this:
customer_id
returning_success
1
True
2
False
3
True
Assuming that is not important if the Complete was after or prior to the Cancellation, you can LEFT JOIN the table with a subquery that only takes the completes. If the result is NULL, then is not have a complete state. Otherwise is true.
As you don't provide your DBMS (Please read: Why should I "tag my RDBMS"?) we take in consideration IFNULL but this can change in other DBMS: https://www.w3schools.com/sql/sql_isnull.asp
SELECT
yt.customer_id,
IFNULL(completes.customer_id,'false','true') as returning_success
FROM
yourtable yt
LEFT JOIN
(
SELECT
customer_id
FROM
yourTable
WHERE transaction_success = 'Complete') completes
ON completes.customer_id = yt.customer_id
 If you just need customers that had had both succesfull and faild transactions, you should implement this:
select customer_id, case when sum(case
when transaction='Faild'
then 1
else 0 end)>0
and
sum(case
when transaction='Complete'
then 1
else 0 end)>0
then 'True'
else 'False' end
returning_success
from table_
group by customer_id
 If you actually do have some timestamp column:
select nvl(c.customer_id, f.customer_id) customer_id
, case when last_complete_time is null
or first_fail_time is null
or first_fail_time>last_complete_time
then 'False'
else 'True' end
returning_success
from (
select customer_id, max(time_) last_complete_time
from table_
group by customer_id
where transaction='Complete'
) c
full join (
select customer_id, min(time_) first_fail_time
from table_
group by customer_id
where transaction='Fail'
) f on c.customer_id=f.customer_id
 You also can use this query to filter all True cases and then just union or join the rest:
select f.customer_id, 'True'
from (
select customer_id, max(time_) last_complete_time
from table_
group by customer_id
where transaction='Complete'
) c
join (
select customer_id, min(time_) first_fail_time
from table_
group by customer_id
where transaction='Fail'
) f on c.customer_id=f.customer_id
where first_fail_time<last_complete_time

Returning the maximum of non-null columns ​from a table

I have a table with 4 columns, one of which is a non-null column, all others can be given a null value.
I just want a SELECT that returns results that have as many non-null columns as possible.
For example:
If I have 5 records in my Table, 1 of those records will have 3 columns with data, 2 of them will have 2 columns with data and 2 of them will have only 1 column with data. In my select, I want as a result only the first option: to bring me 3 columns with data. But it can be just 2 columns with data, it will be dynamic according to the table to be updated.
I'm using Oracle SQL.
One option is a conditional sort based on the count of non-null values in each row, and then a row-limiting clause (available since Oracle 12c). Assuming that the 3 nullable columns are col1, col2 and col3, that would be:
select *
from mytable
order by
case when col1 is null then 0 else 1 end
+ case when col2 is null then 0 else 1 end
+ case when col3 is null then 0 else 1 end desc
fetch first row with ties
If you are running an older version of Oracle, you can get the same result with window function rank():
select *
from (
select
t.*,
rank() over(order by
case when col1 is null then 0 else 1 end
+ case when col2 is null then 0 else 1 end
+ case when col3 is null then 0 else 1 end desc
) rn
from mytable t
) t
where rn = 1

I'm trying to take a record from, for example row 1 and insert it into row 3

I have a field called RecordType that has three different records, 1, 2, 3. Each hold different records. I want to take the the balance from another field I have called Limit from RecordType 1 and insert it into RecordType 3 but I'm just unsure on how to do this. This will be going into a Crystal Report and I want to be able to suppress the RecordType 1 altogether.
I've tried a simple case statement but that's about it, I can't really think of any other ways to do it (I'm sure there's loads).
CASE
WHEN FA.RecordType = 3 THEN
FA.Limit
END AS LimitTest
Current results
Record Type
Limit
1
5,000,301
2
0
3
0
Expected Results
Record Type
Limit
2
0
3
5,000,301
You seem to want to combine the limit for types 1 and 3. You can do this with aggregation on an expression:
select (case when recordtype = 1 then 3 else recordtype end) as recordtype,
sum(limit) as limit
from t
group by (case when recordtype = 1 then 3 else recordtype end);
You can try using sub-query and a Case statement in your select statement, for example:
SELECT [RecordType],
(CASE [RECORDTYPE] WHEN 3 THEN
(SELECT LIMIT from Table_1 WHERE RECORDTYPE = 1)
ELSE LIMIT END) LimitTest
FROM TABLE_1 WHERE RECORDTYPE <> 1
You said:
Sorry my formatting is terrible I'm not sure how to do it properly. But to answer your question no type 1 & 3 will never have the same value as 3 never has a value. I want to basically move the value from type 1 into type 3
Which makes me think that this would be the simplest:
DELETE FROM table WHERE RecordType = 3
UPDATE table SET RecordType = 3 WHERE RecordType = 1
3 never has a value so let's get rid of them first, then 1 has the value but we want it to be 3 so just update all the 1s to be 3s instead
If you're not into deleting it, just mask it instead:
SELECT 3 as RecordType, Limit FROM table WHERE RecordType = 1
If you want to move value from type 1 to type 3 then do simple update in your query.
update t set t.value= t1.value from table as t , table as t1 where t.recordtype=3 and t1.recordtype=1
or
delete from table where recordtype = 3
update recordtype set recordtype=1 where recordtype=3
This will work may be
SELECT
IIF(A.RECORDTYPE = 1,3,A.RECORDTYPE) AS RECORDTYPE,
A.LIMIT
FROM
(
SELECT 1 RECORDTYPE,5000301 LIMIT UNION ALL
SELECT 2 RECORDTYPE,0 LIMIT UNION ALL
SELECT 3 RECORDTYPE,0 LIMIT
) A
WHERE A.RECORDTYPE IN (1,2)
ORDER BY RECORDTYPE
Check this if works for you.

identify rows with not null values in sql

How to retrieve all rows having value in a status column (not null) group by ID column.
Id Name Status
1394 Test 1 Y
1394 Test 2 null
1394 Test 3 null
1395 Test 4 Y
1395 Test 5 Y
I wrote like select * from table where status = 'Y'. It brings me 3 records, how to add condition to bring in only last 2? the 1394 ID have other 2 records, which status is null.
If you want to select groups where the status is only y, you can do:
select t.*
from t
where not exists (select 1
from t t2
where t2.id = t.id and
(t2.Status <> 'Y' or t2.status is null)
);
If you only want the ids, I would use group by and having:
select id
from t
group by id
having min(status) = 'Y' and max(status) = 'Y' and count(*) = count(status);
The last condition checks for no NULL values.
You could also write:
having min(status = 'Y' then 1 else 0 end) = 1
A simple way is:
select * from mytable
where status = 'Y'
and id not in (select id from mytable where status is null)
The existing query "where status = 'Y'" will bring you not null by definition.
If you are trying to get grouped results, a "GROUP BY id" clause will achieve this, which will also require putting id in the select explicitly instead of "*".
Example: SELECT id, COUNT(id) from table where status = 'Y'
If I am reading this correctly you want to bring in the ID for a grouping that never has a NULL status value:
I would use a subquery with a not-exist:
SELECT DISTINCT ID FROM mytable WHERE status IS NULL;
Then filter IDs that do not exist in that list:
SELECT * FROM mytable WHERE id NOT IN (SELECT DISTINCT ID FROM mytable WHERE status IS NULL);
Here are some possible solutions, because I am unclear on exactly what you want as output:
Select Id, Name, Status from table where status is not null;
results in 3 rows:
Id Name Status
1394 Test 1 Y
1395 Test 4 Y
1395 Test 5 Y
Select Id, count(*) as anAmt from table where status is not null group by Id;
/* only retrieves counts per Id */
results in 1 row for each Id:
Id anAmt
1394 1
1395 2

SQL - Combining incomplete

I'm using Oracle 10g. I have a table with a number of fields of varying types. The fields contain observations that have been made by made about a particular thing on a particular date by a particular site.
So:
ItemID, Date, Observation1, Observation2, Observation3...
There are about 40 Observations in each record. The table structure cannot be changed at this point in time.
Unfortunately not all the Observations have been populated (either accidentally or because the site is incapable of making that recording). I need to combine all the records about a particular item into a single record in a query, making it as complete as possible.
A simple way to do this would be something like
SELECT
ItemID,
MAX(Date),
MAX(Observation1),
MAX(Observation2)
etc.
FROM
Table
GROUP BY
ItemID
But ideally I would like it to pick the most recent observation available, not the max/min value. I could do this by writing sub queries in the form
SELECT
ItemID,
ObservationX,
ROW_NUMBER() OVER (PARTITION BY ItemID ORDER BY Date DESC) ROWNUMBER
FROM
Table
WHERE
ObservationX IS NOT NULL
And joining all the ROWNUMBER 1s together for an ItemID but because of the number of fields this would require 40 subqueries.
My question is whether there's a more concise way of doing this that I'm missing.
Create the table and the sample date
SQL> create table observation(
2 item_id number,
3 dt date,
4 val1 number,
5 val2 number );
Table created.
SQL> insert into observation values( 1, date '2011-12-01', 1, null );
1 row created.
SQL> insert into observation values( 1, date '2011-12-02', null, 2 );
1 row created.
SQL> insert into observation values( 1, date '2011-12-03', 3, null );
1 row created.
SQL> insert into observation values( 2, date '2011-12-01', 4, null );
1 row created.
SQL> insert into observation values( 2, date '2011-12-02', 5, 6 );
1 row created.
And then use the KEEP clause on the MAX aggregate function with an ORDER BY that puts the rows with NULL observations at the end. whatever date you use in the ORDER BY needs to be earlier than the earliest real observation in the table.
SQL> ed
Wrote file afiedt.buf
1 select item_id,
2 max(val1) keep( dense_rank last
3 order by (case when val1 is not null
4 then dt
5 else date '1900-01-01'
6 end) ) val1,
7 max(val2) keep( dense_rank last
8 order by (case when val2 is not null
9 then dt
10 else date '1900-01-01'
11 end) ) val2
12 from observation
13* group by item_id
SQL> /
ITEM_ID VAL1 VAL2
---------- ---------- ----------
1 3 2
2 5 6
I suspect that there is a more elegant solution to ignore the NULL values than adding the CASE statement to the ORDER BY but the CASE gets the job done.
i dont know about commands in oracle but in sql you could use some how that
first use pivot table is contains consecutives numbers 0,1,2...
i'm not sure but in oracle the function "isnull" is "NVL"
select items.ItemId,
case p.i = 0 then observation1 else '' end as observation1,
case p.i = 0 then observation1 else '' end as observation2,
case p.i = 0 then observation1 else '' end as observation3,
...
case p.i = 39 then observation4 else '' as observation40
from (
select items.ItemId
from table as items
where items.item = _paramerter_for_retrive_only_one_item /* select one item o more item where you filter items here*/
group by items.ItemId) itemgroup
left join
(
select
items.ItemId,
p.i,
isnull( max ( case p.i = 0 then observation1 else '' end ), '' ) as observation1,
isnull( max ( case p.i = 1 then observation2 else '' end ), '' ) as observation2,
isnull( max ( case p.i = 2 then observation3 else '' end), '' ) as observation3,
...
isnull( max ( case p.i = 39 then observation4), '' ) as observation40,
from
(select i from pivot where id < 40 /*you number of columns of observations, that attach one index*/
)
as p
cross join table as items
lef join table as itemcombinations
on item.itemid = itemcombinations.itemid
where items.item = _paramerter_for_retrive_only_one_item /* select one item o more item where you filter items here*/
and (p.i = 0 and not itemcombinations.observation1 is null) /* column 1 */
and (p.i = 1 and not itemcombinations.observation2 is null) /* column 2 */
and (p.i = 2 and not itemcombinations.observation3 is null) /* column 3 */
....
and (p.i = 39 and not itemcombinations.observation3 is null) /* column 39 */
group by p.i, items.ItemId
) as itemsimplified
on itemsimplified.ItemId = itemgroup.itemId
group by itemgroup.itemId
About pivot table
create an pivot table, Take a look at that
pivot table schema
name: pivot columns: {i : datatype int}
How populate
create foo table
schema foo
name: foo column: value datatype varchar
insert into foo
values('0'),
values('1'),
values('2'),
values('3'),
values('4'),
values('5'),
values('6'),
values('7'),
values('8'),
values('9');
/* insert 100 values */
insert into pivot
select concat(a.value, a.value) /* mysql */
a.value + a.value /* sql server */
a.value | a.value /* Oracle im not sure about that sintax */
from foo a, foo b
/* insert 1000 values */
insert into pivot
select concat(a.value, b.value, c.value) /* mysql */
a.value + b.value + c.value /* sql server */
a.value | b.value | c.value /* Oracle im not sure about that sintax */
from foo a, foo b, foo c
the idea about pivot table can consult in "Transact-SQL Cookbook By Jonathan Gennick, Ales Spetic"
I have to admit that the above solution (by Justin Cave) is simpler and easier to understand but this is another good option
at the end like you said you solved