SELECT Row_number()
OVER (
ORDER BY setsid) AS Set_No,
setsid,
testid
FROM examsets
WHERE testid = 4
Result is :-
Set_No
-------------------
1
2
3
4
5
6
7
I want result As:-
Set_No
-------------------
a
b
c
d
e
f
g
How can I do this?
You can use this. It will not handle cases where you have more than 26 rows returned.
char(96+row_number() over(order by setsid))
Going from AA to ZZ will give you 676 different values.
select char(((T.N / 26) % 26) + 65) + char((T.N % 26) + 65) as Set_No
from (
select row_number() over(order by setsid) - 1 as N
from YourTable
) as T
SQL Fiddle
SELECT
char(ascii(row_number() over (order by setsid))+48) as Set_No
setsid,
testid
FROM
examsets
WHERE
testid = 4
Related
I'm trying to categorize my data based on the existence of text within a variable for each id that I have. For example:
ID Groupname
1 A
1 B
1 F
2 D
2 B
2 C
The result I want would be
ID Groupname Category
1 A AF
1 B AF
1 F AF
2 D D
2 B D
2 C D
I want to do something like the following but I cannot get it to work
Select * ,
CASE WHEN A,F in groupname (partition by id) THEN AF
WHEN D in groupname (partition by id) THEN D
....
ELSE null END
FROM table
Answers in postgres/redshift would greatly be appreciated!
EDIT:
I fixed the problem with F that JNevill brought up.
EDIT2:
One user suggested a simple solution that works if you only need 1 combination. E.g. If i see F or A then it's AF. But if I need to see A and F it will not work.
Here is the simple solution:
WHEN sum(CASE WHEN combo in (20,28,19,27) then 1 end) over (partition by log_id)=1 then 1000
If i want combinations I have to do the following which creates very long code. Is there an easier way to do this?
WHEN sum(CASE WHEN combo in (20,28,19,27) then 1 end) over (partition by log_id)=1
and sum(CASE WHEN groupid in (1048,598,428) then 1 end) over (partition by log_id)=1
then 1000
you're right about case with partitioning, it just requires conditional aggregate
select
*
,case
when sum(case when groupname in ('A','F') then 1 end) over (partition by id)=1 then 'AF'
when sum(case when groupname in ('D') then 1 end) over (partition by id)=1 then 'D'
end as category
from t
one note is that if you want only the pair of A and F to make AF category it's not possible with this syntax... count(distinct case...) over () returns an error and requires more complex query, but from what I see you don't need it since F is not in your sample data
I have to implement a query where the scenario is something like below;
Col_1 Col_2 Col_3 Col_4 Col_5
A AB AC AD AE
B BC BD BE ?
C CD CE ? ?
D DE ? ? ?
E ? ? ? ?
Any help on the below is highly appreciated.
Thanks,
Amit
You need different rows for each column:
select
col_1
,col_1 || min(col_1) over (order by ... rows between 1 following and 1 following)
,col_1 || min(col_1) over (order by ... rows between 2 following and 2 following)
,col_1 || min(col_1) over (order by ... rows between 3 following and 3 following)
,col_1 || min(col_1) over (order by ... rows between 4 following and 4 following)
{
SELECT CHR(64+LEVEL) AS A,
DECODE(SIGN( 4 - LEVEL ) , -1, '?',CHR(64+LEVEL)||CHR(65 +LEVEL)) B,
DECODE(SIGN( 3 - LEVEL ) , -1, '?',CHR(64+LEVEL)||CHR(66 +LEVEL)) C,
DECODE(SIGN( 2 - LEVEL ) , -1, '?',CHR(64+LEVEL)||CHR(67 +LEVEL)) D,
DECODE(sign( 1 - level ) , -1, '?',chr(64+level)||chr(68 +level)) E
from dual connect by level <6;
}
this above is using oracle 10g, other db should have some other strategy.
Assume I have a table like
how can I create a table like
where the groups are created of timeintervals with the length of 1 second.
Thank you in advance!
Here is an idea, but you need a table of numbers
select (m.startts + n.n - 1) as starttime,
(m.startts + n.n) as enddtime,
sum(case when vehicle_type = 'bus' then 1 else 0 end) as bus,
sum(case when vehicle_type = 'car' then 1 else 0 end) as car
from (select min(Timestamp) as startts from table t) m cross join
(select 1 as n union all select 2 union all select 3) n left join
table t
on t.timestamp >= m.startts + n.n - 1 and
t.timestamp < m.startts + n.n
group by m.startts + n.n;
This is a little dangerous because of the floating point arithmetic, but it will probably work for your purposes.
I'm writing a query like this...
select to_char(e_date, 'MON/YYYY') as Month , location_code, count(employee_number) from...
Now I want to group by Month and Location_code. so how to use to_char(e_date, 'MON/YYYY') as Month in group by clause?
EDIT:
select to_char(vheda.e_date, 'MON/YYYY') as Months , hla.location_code, count(vheda.employee_number) emp_count from
virtu.virt_hr_emp_daily_attendance vheda
inner join per_all_people_f papf on vheda.party_id = papf.party_id
inner join per_all_assignments_f paaf on papf.person_id = paaf.person_id
inner join hr_locations_all hla on paaf.location_id = hla.location_id
where (trunc(sysdate) between PAPF.EFFECTIVE_START_DATE and PAPF.EFFECTIVE_END_DATE)
--and (vheda.e_in_time is not null)
and vheda.e_duration <> 0
and (trunc(sysdate) between PAAF.EFFECTIVE_START_DATE and PAAF.EFFECTIVE_END_DATE)
and vheda.e_date between '1-aug-2014' and '31-oct-2014'
group by hla.location_code, vheda.e_date
order by vheda.e_date
OUT PUT WHEN USE GROUP BY CLAUSE group by to_char(vheda.e_date, 'MON/YYYY'), hla.location_code:
ORA-00979: not a GROUP BY expression
00979. 00000 - "not a GROUP BY expression"
*Cause:
*Action:
Error at Line: 58 Column: 37
select to_char(e_date, 'MON/YYYY') as Month , location_code, count(employee_number)
from ...
group by to_char(e_date, 'MON/YYYY'), location_code
You need to group by To_char(vheda.e_date, 'MON/YYYY') and hla.location_code.
SELECT To_char(vheda.e_date, 'MON/YYYY') AS Months,
hla.location_code,
Count(vheda.employee_number) emp_count
FROM virtu.virt_hr_emp_daily_attendance vheda
inner join per_all_people_f papf
ON vheda.party_id = papf.party_id
inner join per_all_assignments_f paaf
ON papf.person_id = paaf.person_id
inner join hr_locations_all hla
ON paaf.location_id = hla.location_id
WHERE ( Trunc(SYSDATE) BETWEEN PAPF.effective_start_date AND
PAPF.effective_end_date )
--and (vheda.e_in_time is not null)
AND vheda.e_duration <> 0
AND ( Trunc(SYSDATE) BETWEEN PAAF.effective_start_date AND
PAAF.effective_end_date )
AND vheda.e_date BETWEEN '1-aug-2014' AND '31-oct-2014'
GROUP BY To_char(vheda.e_date, 'MON/YYYY'),
hla.location_code
ORDER BY vheda.e_date
For example, let's see the same with EMP table,
SQL> SELECT To_char(hiredate, 'MON/YYYY') AS Months,
2 deptno,
3 Count(empno) emp_count
4 FROM emp
5 GROUP BY To_char(hiredate, 'MON/YYYY'),
6 deptno
7 /
MONTHS DEPTNO EMP_COUNT
-------- ---------- ----------
DEC/1980 20 1
JUN/1981 10 1
NOV/1981 10 1
MAY/1987 20 1
FEB/1981 30 2
MAY/1981 30 1
DEC/1981 30 1
JAN/1982 10 1
SEP/1981 30 2
DEC/1981 20 1
APR/1981 20 1
APR/1987 20 1
12 rows selected.
SQL>
select EXTRACT(MONTH FROM e_date)||'/'|| EXTRACT(Year FROM e_date) as months , location_code, count(employee_number)
FROM ...
group by EXTRACT(MONTH FROM e_date)||'/'|| EXTRACT(Year FROM e_date), location_code
You can also use EXTRACT function in GROUP BY clause..
i hope it helps..
I have the following tables in SQL Server:
user_id, value, date, action_id
----------------------------------
1 A 1/3/2012 null
1 K 1/4/2012 null
1 B 1/5/2012 null
2 X 1/3/2012 null
2 K 1/4/2012 1
3 K 1/3/2012 null
3 L 1/4/2012 2
3 K 1/5/2012 3
4 K 1/3/2012 null
action_id, state
----------------------------------
1 0
2 1
3 1
4 0
5 1
I need to return the most recent record for each user where the value is 'K', the action id is either null or its state is set to 1. Here's the result set I want:
user_id, value, date, action_id
----------------------------------
3 K 1/5/2012 3
4 K 1/3/2012 null
For user_id 1, the most recent value is B and its action id is null, so I consider this the most recent record, but it's value is not K.
For user_id 2, the most recent value is K, but action id 1 has state 0, so I fallback to X, but X is not K.
user_id 3 and 4 are straightforward.
I'm interested in Linq to SQL query in ASP.NET, but for now T-SQL is fine too.
The SQL query would be :
Select Top 1 T1.* from Table1 T1
LEFT JOIN Table2 T2
ON T1.action_id = T2.action_id
Where T1.Value = 'K' AND (T1.action_id is null or T2.state = 1)
Order by T1.date desc
LINQ Query :
var result = context.Table1.Where(T1=> T1.Value == "K"
&& (T1.action_id == null ||
context.Table2
.Where(T2=>T2.State == 1)
.Select(T2 => T2.action_id).Contains(T1.action_id)))
.OrderByDescending(T => T.date)
.FirstOrDefault();
Good Luck !!
This query will return desired result set:
SELECT
*
FROM
(
SELECT
user_id
,value
,date
,action_id
,ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date DESC) RowNum
FROM
testtable
WHERE
value = 'K'
) testtable
WHERE
RowNum = 1
You can also try following approach if user_id and date combination is unique
Make sure to get the order of predicates in the join to be able to use indexes:
SELECT
testtable.*
FROM
(
SELECT
user_id
,MAX(date) LastDate
FROM
testtable
WHERE
value = 'K'
GROUP BY
user_id
) tblLastValue
INNER JOIN
testtable
ON
testtable.user_id = tblLastValue.user_id
AND
testtable.date = tblLastValue.LastDate
This would select the top entries for all users as described in your specification, as opposed to TOP 1 which just selects the most recent entry in the database. I'm assuming here that your tables are named users and actions:
WITH usersactions as
(SELECT
u.user_id,
u.value,
u.date,
u.action_id,
ROW NUMBER() OVER (PARTITION BY u.user_id ORDER BY u.date DESC, u.action_id DESC) as row
FROM users u
LEFT OUTER JOIN actions a ON u.action_id = a.action_id
WHERE
u.value = 'K' AND
(u.action_id IS NULL OR a.state = 1)
)
SELECT * FROM usersactions WHERE row = 1
Or if you don't want to use a CTE:
SELECT * FROM
(SELECT
u.user_id,
u.value,
u.date,
u.action_id,
ROW NUMBER() OVER (PARTITION BY u.user_id ORDER BY u.date DESC, u.action_id DESC) as row
FROM users u
LEFT OUTER JOIN actions a ON u.action_id = a.action_id
WHERE
u.value = 'K' AND
(u.action_id IS NULL OR a.state = 1)
) useractions
WHERE row = 1