Conditionally append a character in select statement - sql

Functionality I'm trying to add to my DB2 stored procedure:
Select a MIN() date from a joined table column.
IF there was more than one row in this joined table, append a " * " to the date.
Thanks, any help or guidance is much appreciated.

It's not clear which flavor of DB2 is needed nor if any suggestion worked. This works on DB2 for i:
SELECT
T1.joinCol1,
max( T2.somedateColumn ),
count( t2.somedateColumn ),
char(max( T2.somedateColumn )) concat case when count( T2.somedateColumn )>1 then '*' else '' end
FROM joinFile1 t1 join joinFile2 t2
on joinCol1 = joinCol2
GROUP BY T1.joinCol1
ORDER BY T1.joinCol1
The SQL is fairly generic, so it should translate to many environments and versions.
Substitute table and column names as needed. The COUNT() here actually counts rows from the JOIN rather than the number of times the specific date occurs. If a count of duplicate dates is needed, then some changes to this example are also needed.

Hope this helps
Say I have result coming as
1 Jeff 1
2 Jeff 333
3 Jeff 77
4 Jeff 1
5 Jeff 14
6 Bob 22
7 Bob 4
8 Bob 5
9 Bob 6
Here the value 1 is repeated twice(in 3 column)
So, this query gets the count as 2 along with the * concatenated along with it
SELECT A.USER_VAL,
DECODE(A.CNT, '1', A.CNT, '0', A.CNT, CONCAT(A.CNT, '*')) AS CNT
FROM (SELECT DISTINCT BT.USER_VAL, CAST(COUNT(*) AS VARCHAR2(2)) AS CNT
FROM SO_BUFFER_TABLE_8 BT
GROUP BY BT.USER_VAL) A

Related

result table description

I want to write a query in SQL. Can someone help me for writing oracle sql query for below result table
Table 1 Data
prodno description
1 Laptop
2 Charger
3 Mouse
Table 2 Data
prodno prodset_no
1 1
2 1
3 1
1 2
3 2
1 3
2 3
Result Table
prodset_no prodset_desc
1 Laptop,Charger,Mouse
2 Laptop,Mouse
3 Laptop,Charger
JOIN the two table and then use listagg to produce comma separated output:
select t2.prodset_no,
listagg(t1.description, ',') within group (
order by t1.prodno
) prodset_desc
from table2 t2
join table1 t1 on t2.prodno = t1.prodno
group by t2.prodset_no;
Also, worth a note that the listagg has a limit of 4000 bytes. If you hit that limit, you can either use XMLAGG or rethink the problem and not do it in SQL at all but rather handle it in your application code.

SQL If condition

I have a table called Train with this sample data:
train_id strt_stn_id end_stn_id direction
---------------------------------------------
1 1 10 D
2 1 21 D
3 10 1 U
4 1 5 D
5 1 15 D
and a Station table with this data:
stn_id stn_name
---------------------
1 Churchgate
2 Marine Lines
3 Charni Road
4 Grant Road
5 Mumbai Central
6 Mahalaxmi
7 Lower Parel
8 Elphinstone Road
9 Dadar
10 Matunga Road
11 Mahim
12 Bandra
13 Khar Road
14 Santacruz
15 Vile Parle
I want station name depending on the condition. If strt_stn_id > end_stn_id, I want station name of end_stn_id else station name of strt_stn_id.
So how to use if condition in a SQL query?
Try this:
SELECT T.*, S.stn_name
FROM Train T
INNER JOIN Station S
ON CASE WHEN T.strt_stn_id > T.end_stn_id
THEN T.end_stn_id ELSE T.strt_stn_id END = S.stn_id
use case
http://www.tizag.com/sqlTutorial/sqlcase.php
gives an example of how to use
'station' = CASE
WHEN (strt_stn_id > end_stn_id) THEN (end_stn_id)
ELSE (strt_stn_id)
END
Although you can definitely put the logic in the on clause, I much prefer to do two separate joins and put the logic in the select clause:
SELECT T.*,
(case when t.strt_stn_id > t.end_stn_id then starts.stn_name
else ends.stn_name
end) as TheName
FROM Train T INNER JOIN
Station Starts
ON T.strt_stn_id = Starts.stn_id inner join
Station ends
on T.end_stn_id = ends.stn_id
In general, a case statement or function all in an on clause prevents the engine from using indexes. If the tables have reasonable indexes (such as on their primary keys), this version will work better. As an aside, I also think having the logic in the select clause is more understandable, but I recognize that others might disagree.

SQL Query to find which group does not have a given value

I am using T-SQL.
Say if I have the following
Value Nbr
----- ---
one 6
one 7
one 8
two 6
two 7
three 5
three 3
three 2
In the above table, I need to find which group does not have 6 in it.
In this case, it is three as it does not have 6 in it.
What would be the best approach to do this?
I tried:
select Value from tbl1
where nbr <> 6
group by Value
but did not get the intended result.
select distinct value
from tbl1
where value not in
(
select distinct value
from tbl1
where nbr = 6
)

Access SQL query to mailmerge

How can I transform this table from this
id name
1 sam
2 nick
3 ali
4 farah
5 josef
6 fadi
to
id1 name1 id2 name2 id3 name3 id4 name4
1 sam 2 nick 3 ali 4 farah
5 josef 6 fadi
the reason i need this is i have a database and i need to do a mail merge using word and I want to print every 4 rows on one page, MS word can only print one row per page, so using an SQL query I want one row to represent 4 rows
thanks in advance
Ali
You don't need to create a query for this in Access. Word has a merge field called <<Next Record>> which forces moving to the next record. If you look at how label documents are created using the Mail Merge Wizard, you'll see that's how it's done.
Updated - Doing this in SQL
The columns in simple SELECT statements are derived from the columns from the underlying table/query (or from expressions). If you want to define columns based on the data, you need to use a crosstab query.
First create a query with a running count for each person (say your table is called People), and calculate the row and column position from the running count:
SELECT People.id, Count(*)-1 AS RunningCount, int(RunningCount/4) AS RowNumber, RunningCount Mod 4 AS ColumnNumber
FROM People
LEFT JOIN People AS People_1 ON People.id >= People_1.id
GROUP BY People.id;
(You won't be able to view this in the Query Designer, because the JOIN isn't comparing with = but with >=.)
This query returns the following results:
id Rank RowNumber ColumnNumber
1 0 0 0
2 1 0 1
3 2 0 2
4 3 0 3
5 4 1 0
6 5 1 1
Assuming this query is saved as Positions, the following query will return the results:
TRANSFORM First(Item) AS FirstOfItem
SELECT RowNumber
FROM (
SELECT ID AS Item, RowNumber, "id" &( ColumnNumber + 1) AS ColumnHeading
FROM Positions
UNION ALL SELECT Name, RowNumber, "name" & (ColumnNumber +1)
FROM Positions
INNER JOIN People ON Positions.id = People.id
) AS AllValues
GROUP BY AllValues.RowNumber
PIVOT AllValues.ColumnHeading In ("id1","name1","id2","name2","id3","name3","id4","name4");
The UNION is there so each record in the People table will have two columns - one with the id, and one with the name.
The PIVOT clause forces the columns to the specified order, and not in alphabetical order (e.g. id1, id2 ... name1, name2...)

SQLite: Get Total/Sum of Column

I am using SQLite and am trying to return the total of one column buy_price in the column TOTAL while at the same time returning all of the data. I do not want/need to group the data as I need to have the data in each returned row.
id date pool_name pool_id buy_price TOTAL
1 09/01/12 azp 5 20
2 09/02/12 mmp 6 10
3 09/03/12 pbp 4 5
4 09/04/12 azp 7 20
5 09/05/12 nyp 8 5 60
When I include something like SUM(buy_price) as TOTAL it only returns one row. I need all rows returned along with the total of all buy_price entries.
It sounds like this is what you are looking for:
select id,
dt,
pool_name,
pool_id,
buy_price,
(select sum(buy_price) from yourtable) total
from yourtable
see SQL Fiddle with Demo
Select * from yourtable
union
select 'Total',
' ',
' ',
' ',
sum(buy_price)
from yourtable
you can add a row on the bottom like this instead of adding a new column...