7

I have SQL Query, I want to add insert blank row in result so it is easy to see the result. I want to insert it after ORDER BY. don't know if it could be done.

Here is my select statement.

SELECT TableName.CREWACTIONFACTID
      ,TableName.CREWKEY as CrewKey
      ,TableName.EVENTKEY as EventID
      ,TableName.ACTIONSEQUENCE
      ,case TableName.ACTIONTYPE
            when 'DISPATCHED' then '2-Dispatched'
            when 'ASSIGNED' then '1-Assigned'
            when 'ENROUTE' then '3-Entoute'
            when 'ARRIVED' then '4-Arrived'
            else 'unknown'
            end  as Type
      ,TableName.STARTDATETIME as StartTime
      ,TableName.ENDDATETIME as EndTIme
      ,TableName.DURATION as Duration

  FROM DatabaseName.TableName TableName
  where 
    To_Date(to_char(TableName.STARTDATETIME, 'DD-MON-YYYY')) >= To_Date('?DATE1::?','MM/DD/YYYY')
    AND To_Date(to_char(TableName.ENDDATETIME, 'DD-MON-YYYY')) <= To_Date('?DATE2::?','MM/DD/YYYY')
   ORDER BY TableName.EVENTKEY, TableName.STARTDATETIME,TableName.ACTIONSEQUENCE
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
Mowgli
  • 3,422
  • 21
  • 64
  • 88

4 Answers4

6

You can, pretty much as Michael and Gordon did, just tack an empty row on with union all, but you need to have it before the order by:

...
and to_date(to_char(t.enddatetime, 'DD-MON-YYYY')) <=
    to_date('?DATE2::?','MM/DD/YYYY')
union all
select null, null, null, null, null, null, null, null
from dual
order by eventid, starttime, actionsequence;

... and you can't use the case that Gordon had directly in the order by because it isn't a selected value - you'll get an ORA-07185. (Note that the column names in the order by are the aliases that you assigned in the select, not those in the table; and you don't include the table name/alias; and it isn't necessary to alias the null columns in the union part, but you may want to for clarity).

But this relies on null being sorted after any real values, which may not always be the case (not sure, but might be affected by NLS parameters), and it isn't known if the real eventkey can ever be null anyway. So it's probably safer to introduce a dummy column in both parts of the query and use that for the ordering, but exclude it from the results by nesting the query:

select crewactionfactid, crewkey, eventid, actionsequence, type,
    starttime, endtime, duration
from (
    select 0 as dummy_order_field,
        t.crewactionfactid,
        t.crewkey,
        t.eventkey as eventid,
        t.actionsequence,
        case t.actiontype
            when 'DISPATCHED' then '2-Dispatched'
            when 'ASSIGNED' then '1-Assigned'
            when 'ENROUTE' then '3-Enroute'
            when 'ARRIVED' then '4-Arrived'
            else 'unknown'
        end as type,
        t.startdatetime as starttime,
        t.enddatetime as endtime,
        t.duration
    from schema_name.table_name t
    where to_date(to_char(t.startdatetime, 'DD-MON-YYYY')) >=
        to_date('?DATE1::?','MM/DD/YYYY')
    and to_date(to_char(t.enddatetime, 'DD-MON-YYYY')) <=
        to_date('?DATE2::?','MM/DD/YYYY')
    union all
    select 1, null, null, null, null, null, null, null, null
    from dual
)
order by dummy_order_field, eventid, starttime, action sequence;

The date handling is odd though, particularly the to_date(to_char(...)) parts. It looks like you're just trying to lose the time portion, in which case you can use trunk instead:

where trunc(t.startdatetime) >= to_date('?DATE1::?','MM/DD/YYYY')
and trunc(t.enddatetime) <= to_date('?DATE2::?','MM/DD/YYYY')

But applying any function to the date column prevents any index on it being used, so it's better to leave that alone and get the variable part in the right state for comparison:

where t.startdatetime >= to_date('?DATE1::?','MM/DD/YYYY')
and t.enddatetime < to_date('?DATE2::?','MM/DD/YYYY') + 1

The + 1 adds a day, so id DATE2 was 07/12/2012, the filter is < 2012-07-13 00:00:00, which is the same as <= 2012-07-12 23:59:59.

Alex Poole
  • 183,384
  • 11
  • 179
  • 318
  • Gordon has also mentioned that Dual don't with all sql, I followed your solution, I still get `FROM` error `One or more errors occurred during processing of command. ORA-00923: FROM keyword not found where expected at` – Mowgli Jul 12 '12 at 13:11
  • Alex, Thanks for think for the `where` condition, I will follow and fix that after this. – Mowgli Jul 12 '12 at 13:16
  • Well that exact code runs for me in SQL*Plus, except I used my own schema and table name, and replaced `?DATE1::?` with `07/11/2012`. As that seemed to work for you originally that probably isn't the problem. The only thing that seems suspicious is the use of `type` as an alias since it's a reserved word, but again you had that before. Can you run it directly against your DB? – Alex Poole Jul 12 '12 at 13:22
  • I take the `from` error back, I was missing comma silly mistake.. and it worked but it didn't add empty row after it was order by, almost there thanks – Mowgli Jul 12 '12 at 13:41
  • you sure I am not missing any case statement to select 1 or 0 – Mowgli Jul 12 '12 at 14:10
  • The `select ... from dual` creates an empty row, so it should be there, if hard to spot. If you're displaying this on your HTML page, check the source and see if it's there - depending on how the data is formatted it may be *really* hard to spot, and you might need to use something like `'&nbsp'` instead of null. Another reason this is a bad idea! – Alex Poole Jul 12 '12 at 14:11
  • Yep it is there in source code, is there a way to fix it? instead of null, can I put `'--'`? – Mowgli Jul 12 '12 at 14:24
  • 1
    You'll have to experiment with a value; `' '` will make a non-breaking space which may generate the space you want, but depends what container it's in. Maybe `'
    '` would do what you want. You'll have to figure out what suits you best. But this is now an HTML question, not a SQL one.
    – Alex Poole Jul 12 '12 at 14:30
  • thanks for help really appericate it..and I hope I will be able to fix this html problem because HTML is automatically generated by the software i am writting SQL query in it is more of ASP/ASPX. – Mowgli Jul 12 '12 at 14:42
3

Your question is rather complicated. SQL only guarantees the ordering of results, through the order by. It does not guarantee what happens afterwards. So, you have to put in the blank row and then add the information afterwords:

<your select query minus the order by>
union all
select NULL as CrewActionFatId, . . .
order by (case when CrewActionFactId is NULL then 1 else 0 end),
         TableName.EVENTKEY, TableName.STARTDATETIME,TableName.ACTIONSEQUENCE

In practice, @Michael's solution would normally work. But it is not guaranteed.

Also, you should decide whether you want blanks or NULLs. I'm guessing the first id is a number, so I'm setting it to NULL.

In general, such presentation niceties are handled by the calling application. Perhaps you need a better SQL query tool to see the data more cleanly.

Here is what the full query would look like (with all fields set to NULL, you can change to blank if you prefer):

SELECT TableName.CREWACTIONFACTID, TableName.CREWKEY as CrewKey,
       TableName.EVENTKEY as EventID, TableName.ACTIONSEQUENCE,
       (case TableName.ACTIONTYPE
            when 'DISPATCHED' then '2-Dispatched'
            when 'ASSIGNED' then '1-Assigned'
            when 'ENROUTE' then '3-Entoute'
            when 'ARRIVED' then '4-Arrived'
            else 'unknown'
        end) as Type,
       TableName.STARTDATETIME as StartTime,
       TableName.ENDDATETIME as EndTIme,
       TableName.DURATION as Duration
FROM DatabaseName.TableName TableName
where To_Date(to_char(TableName.STARTDATETIME, 'DD-MON-YYYY')) >= To_Date('?DATE1::?','MM/DD/YYYY') AND
      To_Date(to_char(TableName.ENDDATETIME, 'DD-MON-YYYY')) <= To_Date('?DATE2::?','MM/DD/YYYY')
union all
SELECT NULL AS CREWACTIONFACTID, NULL AS CrewKey, NULL AS EventID,
       NULL AS ACTIONSEQUENCE, NULL AS Type, NULL AS StartTime, NULL AS EndTime,
       NULL AS Duration
from dual
ORDER BY (case when CrewActionFactId is NULL then 1 else 0 end),
         TableName.EVENTKEY, TableName.STARTDATETIME, TableName.ACTIONSEQUENCE 
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • Thanks for reply, I am very new to SQL so I am having hard time to understand the code your posted,
    so said you said on top I need put my select query than `union all` and I don't know wht is `. . .` is for please explain. Thanks again
    – Mowgli Jul 11 '12 at 17:25
  • nevermind about `. . .` I understand now so I replaced `' '` with `null` but do I need `< >` or `( ) ` Thanks – Mowgli Jul 11 '12 at 17:29
  • Thanks for edit, and updating, I tried that but I get `from missing error` `ORA-00923: FROM keyword not found where expected at ` – Mowgli Jul 11 '12 at 18:33
  • 1
    Added in "from dual". Some databases allow a select with no "from" clause to return a single row; others such as Oracle do not. – Gordon Linoff Jul 11 '12 at 18:35
  • so Oracle don't allow, selecting null with table, what can be alternate solution for this? – Mowgli Jul 11 '12 at 18:46
  • @Mogli. Yes and no. Oracle (and no other database) allows you to union together queries with different numbers of columns (although postgres has a nice workaround for this). My comment was only about syntax. The syntax for the second part of the union differs by database. – Gordon Linoff Jul 11 '12 at 18:53
  • Thanks Gordon for help, hopefully someone from Oracel side will be able see the problem – Mowgli Jul 11 '12 at 19:06
2

An odd request to be sure, but yes it can be done by making a UNION against a row of literal blank values. To make sure the order-by is applied to the real query, enclose the whole thing in () and then union it against the blank row.

SELECT * FROM
(SELECT TableName.CREWACTIONFACTID
  ,TableName.CREWKEY as CrewKey
  ,TableName.EVENTKEY as EventID
  ,TableName.ACTIONSEQUENCE
  ,case TableName.ACTIONTYPE
        when 'DISPATCHED' then '2-Dispatched'
        when 'ASSIGNED' then '1-Assigned'
        when 'ENROUTE' then '3-Entoute'
        when 'ARRIVED' then '4-Arrived'
        else 'unknown'
        end  as Type
  ,TableName.STARTDATETIME as StartTime
  ,TableName.ENDDATETIME as EndTIme
  ,TableName.DURATION as Duration
FROM DatabaseName.TableName TableName
where 
To_Date(to_char(TableName.STARTDATETIME, 'DD-MON-YYYY')) >= To_Date('?DATE1::?','MM/DD/YYYY')
AND To_Date(to_char(TableName.ENDDATETIME, 'DD-MON-YYYY')) <= To_Date('?DATE2::?','MM/DD/YYYY')
ORDER BY TableName.EVENTKEY, TableName.STARTDATETIME,TableName.ACTIONSEQUENCE
)
UNION ALL
SELECT 
  '' AS CREWACTIONFACTID,
  '' AS CrewKey,
  '' AS EventID,
  '' AS ACTIONSEQUENCE,
  '' AS Type,
  '' AS StartTime,
  '' AS EndTime,
  '' AS Duration
FROM dual

Finally, depending on how you are presenting this result, I would look into other methods of spacing out the result. Appending blank rows to a query for presentation purposes flies in the face of separation of business and presentation logic.

Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
  • Adding a `UNION ALL` doesn't guarantee any particular order. It would be perfectly legitimate for an implementation to insert the extra row anywhere in the results. – Martin Smith Jul 11 '12 at 16:13
  • Thanks for help, I tired that but I am getting error when I run it. `System.Data.OleDb.OleDbException: ORA-00907: missing right parenthesis at` – Mowgli Jul 11 '12 at 17:17
  • @Mogli Maybe because there was an extra linebreak before the `FROM` clause. Otherwise, there are no unbalanced parens. – Michael Berkowski Jul 11 '12 at 17:40
  • @Michael nope I looked for that too, also looked for typo but nothing found – Mowgli Jul 11 '12 at 18:32
  • @Mogli Reading docs, apparently Oracle doesn't like `ORDER BY` for a union component, even when wrapped in `()`, unless the whole thing is presented as an inline view. I added a `SELECT * FROM` to the top. Does that help? if not, I'm kind of at a loss without an oracle instance to test right now – Michael Berkowski Jul 11 '12 at 18:39
  • @Michael nope I tried that too, it throws same from missing `From` error. – Mowgli Jul 11 '12 at 18:47
  • @Mogli Because this wasn't originally tagged Oracle. Oracle requires the FROM clause as I alluded to in my original answer. Just added `FROM dual` – Michael Berkowski Jul 11 '12 at 18:49
  • @Michael this page has similar answer on bottom but I cannot immplement on query (bottom solution) [This Page](http://stackoverflow.com/questions/2602531/union-on-two-tables-with-a-where-clause-in-the-one) – Mowgli Jul 11 '12 at 18:56
1

The result will be desplayed in an HTML page.

So, use SQL to extract the data, not to format the output. Depending on the page structure and layout, there are a lot of solutions. Have a look here.

Alberto De Caro
  • 5,147
  • 9
  • 47
  • 73
  • I don't think it matters, I can run same query in SQLPLUS but output should be same and that link has layout and I cannot edit any part of HTML codes it is all generated by software itself. – Mowgli Jul 11 '12 at 19:24