I have a complex sorting problem with my SQL statement. I have a table with the following columns.
No Time Value
-- ---- -----
1 0900 ''
2 1030 ''
3 1020 ''
4 1010 ''
5 1100 ''
1 1015 'P'
2 1045 'P'
I want to sort this table by doing the following steps.
Select rows from the table where Value is '' (empty string) and sort it by No.
Select rows from the same table where Value is 'P' and then sort it by time.
Select each row from 2) and insert into 1) by time.
The result should be something like this.
No Time Value
-- ---- -----
1 0900 ''
1 1015 'P'
2 1030 ''
3 1020 ''
4 1010 ''
2 1045 'P'
5 1100 ''
How can I do this in SQL?
Edit: thanks for comments.
On rereading, I don't think part 3 of your question makes sense. The result from step 1) is not sorted by time, and you cannot insert in it by time.
For example, in your example result, the second row is has time 1015, that is between 0900 and 1030. But it could also be between the 1020 and 1010 rows further on?
Unfortunately, I don't think you can do this with a standard SQL query, and the reason is that your algorithm is not set-oriented. Your sample dataset illustrates this -- you have the first 'P' record showing up between the 0900 and 1030 records, but it would be just as appropriate to put it between the 1010 and 1045 records based on your criteria. If it's correct to have it in the position you show, you need to modify your condition to be something like "place each row from #2 between the first two rows in #1 that bracket it in time", where "first" is defined by the sorting criteria of #1.
The upshot is that this type of setup will likely force you into a cursor-based solution. You might be able to avoid this if you can identify a composite value to order upon, but based on what you have above I don't see what that might be.
It seems like you can express your need in a simpler need.
You always sort by time, possibly also by Value then by no.
sort by time, value, no
This will sort everything by time. For two identical times, the sorting on value will be applied, etc.
You could sort on a unique number, that you build to combine your criteria. But that would be more complex.
Related
My question is related to Oracle sql. I have a two tables say, study table and another one is study part table. Stdyno is the primary key in study table and (stydyno + sqncno) is the primary key in studypart table.
EG: studypart table has data as below.
studyNo sqnc part approvalIN
--------------------------------
123 1 fgh Y
123 2 jhf N
123 3 rty N
456 1 wer N
456 2 wdg N
456 3 ghg N
I need query in such a way that my output from studypart table gives result
as study number which has all the approvalIn as N. If it has at least one of the approvalIn as 'Y'
then that studyno should be excluded from the result.
Desired output:
studyno: 456
I tried this implementation in stored procedure taking Y and N approvalIn count separately ie,
if a studyno has both the count then exclude it and
if it has only one count say either N or Y the include it.
But i would like to know how to achieve this is query.
You can do it by excluding those rows whose count of "approvalIN = 'N'" does not match the total count of "approvalIN" values.
SELECT STUDYNO
FROM tab
GROUP BY STUDYNO
HAVING SUM(CASE WHEN approvalIN = 'N' THEN 1 END) = COUNT(approvalIN)
Check the demo here.
Below are the input and output details.Any database Oracle, SQL Server and MySQL should do for the answers.I am not able to derive the logic to rank data which will help me to pivot.
My source is a flat file which contains data like below.I have loaded that file into one of the tables in Oracle.
Source Input:
**Flatfile1**
**Coulmn1**
Kamesh
65
5000
123456789
Nanu
45
3000
321654789
Expected Output:
Name Age Salary Mobilenumber
Kamesh 65 5000 123456789
Nanu 45 3000 321654789
After loading into one of the tables I am applying the logic to number this data which will eventually look like below:
Column1 Datavalue
Kamesh 1
65 1
5000 1
123456789 1
Nanu 2
45 2
3000 2
321654789 2
However, I am not able to derive logic (I tried with Rank) which will give me sequence number like this without having any key field.Hope this explains situation.
Thanks!!
Oracle doesn't store the rows in order, if you do select * from table1 multiple times you could get rows in different orders according to db operations and caching
Therefore if you have a table like that with no other column it's impossible to "pivot" the data.
I strongly suggest to save data in a normalized form, if you can't consider adding a column with a row ID populated automatically (identity column in oracle 12, trigger+ sequence in previous version)
Once you have your rows in order it will be easy to organize your data
I have two table, My first table look like this
tblRecords
Series_Start Series_End
1001 1095
And my second table
tblDetail
Series_StartUsed Series_EndUsed
1011 1021
1051 1060
My goal is to select series in tblRecords not in tblDetail. Sample output is
Series_Start Series_End
1001 1010
1031 1050
1061 1095
Any idea what is the correct SQL script with this?
If I understand your requirement correctly, this query might work (not tested):
select zx.Series_start, zx.Series_End from (
select r.Series_start,
r.Series_End,
case when (select 1 from tblDetail d where (d.Series_StartUsed <= r.Series_End and (d.Series_EndUsed >= r.Series_start or d.Series_StartUsed >= r.Series_Start))) is null then 0 else 1 end as isUsed
from tblRecords r) zx
where zx.isUsed = 0
I might have messed up the actual condition (third select variable), so play around with it if needed as I don't have a way to easily test it right now.
Also, the above query is pretty inefficient so it is not appropriate if you want to use it for extremely large datasets as something routine. You will probably need to write a stored procedure if you want to do that.
I have a requirement wherein i need to find the record number of the records that are returned from the resultset. I know that i can use ROWNUM to get the record number from the resultset but my issue is slightly different. below are the details
Table : ProcessSummary
Columns:
PS_PK ProcessId StepId AsscoiateId ProcessName AssetAmount
145 25 50 Process1 3,500.00
267 26 45 Process2 4,400.00
356 27 70 Process3 2,400.00
456 28 80 90 Process4 780.00
556 29 56 67 Process5 4,500.00
656 45 70 Process6 6,000.00
789 31 75 Process7 8,000.00
Now what i need to do is fetch all the records from the ProcessSummary Table when either of ProcessId OR StepId OR AssociateId is NULL. I wrote the below query
select * from ProcessSummary where ProcessId IS NULL OR StepId IS NULL OR AsscoiateId IS NULL
As expected i got 1st, 2nd, 3rd, 6th and 7th records in the resultset that got returned.
Now what i need is to get the records numbers 1,2,3,6,7. I tried to use the ROWNUM as below but i got the values of 1,2,3,4,5 and not 1,2,3,6,7.
select ROWNUM from ProcessSummary where ProcessId IS NULL OR StepId IS NULL OR AsscoiateId IS NULL
Is it possible to get the ROWNUM values in the sequence that i want and if yes then can you please let me know how can i do this. Also if ROWNUM cannot be used then what would be the other option that i can use to get the result in the form that i want.
Any help would be greately appericiated as i could not find much on the net or SO regarding this sort of requirement.
Thanks
Vikeng21
rownum is an internal numbering that gives you a row number based on the current query results only, so that numbering is not tied to a specific record, and it will change when you change the data or the query.
But the numbering you ask for is already in your table. It looks like you just need to SELECT PS_PK .. instead. PS_PK is the field in your table that contains the actual number you want.
You can generate a numbering using an analytical function, and then filter that query. You need some fields to order by, though. In this case I've chosen PS_PK, but it can be another field, like ProcessName or a combination of other fields as well.
select
*
from
(select
dense_rank() over (order by PS_PK) as RANKING,
p.*
from
ProcessSummary p)
where
ProcessId IS NULL OR StepId IS NULL OR AsscoiateId IS NULL
So, in this query, first a numbering is calculated for each row that is returned from the inner query. The numbering is returned as the field RANKING. And then the other query filters further, but still will return the field RANKING with the original numbering.
Instead of dense_rank there is also rank and row_number. The differences are subtle, but you can just experiment and read some docs here and here to learn about the differences and see which one fits you best.
Note that this might slow down your query, because the inner query first generates a number for each row in the table (there is no filtering on that level now).
I have a SQL problem that I don't have the vocabulary to explain very well.
Here is a simplified table. My goal is to identify groups where the Tax_IDs are not equal. In this case, the query should return groups 1 and 3.
Group Line_ID Tax_ID
1 1001 11
1 1002 13
2 1003 17
2 1004 17
3 1005 23
3 1006 29
I can easily perform comparisons across rows, however I do not know how to perform comparisons "down" a table (here is really where my vocabulary fails me). I.e. what is the syntax that will cause SQL to compare Tax_ID values within groups?
Any help appreciated,
OB
The simplest way is to use group by with a having clause:
select "group"
from t
group by "group"
having min(tax_id) <> max(tax_id);
You can also phrase the having clause as:
having count(distinct tax_id) > 1;
However, count(distinct) is more expensive than just a min() or max()operation.