I am displaying three fields from my query, and I want to display a distinct banking_no. I still want to display the other fields even they are not distinct. Please help.
SELECT C.RECEIPT_OFFICE_PREFIX, B.BANKING_NO, B.STATUS_CD
FROM TControl B, TComponent C
WHERE C.DEPOSIT_BANK_ACCT = 'xxx-xxxxxx-xxxxx'
AND B.BANKING_NO = C.BANKING_NO
AND B.COMPANY_ID = C.COMPANY_ID
AND B.RECEIPT_OFFICE_PREFIX = C.RECEIPT_OFFICE_PREFIX
AND B.STATUS_CD != 'C'
ORDER BY B.BANKING_NO
I am using Sybase ASE 12.5
More recent versions of Sybase support row_number(). You would use it in a subquery like this:
SELECT RECEIPT_OFFICE_PREFIX, BANKING_NO, STATUS_CD
FROM (SELECT C.RECEIPT_OFFICE_PREFIX, B.BANKING_NO, B.STATUS_CD,
ROW_NUMBER() OVER (PARTITION BY B.BANKING_NO ORDER BY B.BANKING_NO) as seqnum
FROM TControl B JOIN
TComponent C
ON B.BANKING_NO = C.BANKING_NO AND B.COMPANY_ID = C.COMPANY_ID
WHERE C.DEPOSIT_BANK_ACCT = 'xxx-xxxxxx-xxxxx' AND
B.RECEIPT_OFFICE_PREFIX = C.RECEIPT_OFFICE_PREFIX AND
B.STATUS_CD != 'C'
) BC
WHERE seqnum = 1
ORDER BY BANKING_NO;
What you want may not be called distint. If the rest of data is the same just using a DISTINCT will do. However if data may be different you need to tell what result should the database choose. the first row? the last row?
If you do not mind just use;
SELECT DISTINCT MAX(C.RECEIPT_OFFICE_PREFIX), B.BANKING_NO, MAX(B.STATUS_CD)
FROM TControl B, TComponent C
WHERE C.DEPOSIT_BANK_ACCT = 'xxx-xxxxxx-xxxxx'
AND B.BANKING_NO = C.BANKING_NO
AND B.COMPANY_ID = C.COMPANY_ID
AND B.RECEIPT_OFFICE_PREFIX = C.RECEIPT_OFFICE_PREFIX
AND B.STATUS_CD != 'C'
GROUP BY B.BANKING_NO
In you need to choose one row use Gordon solution.
Related
I will need to list down duplicate functions within the responsibility name in Oracle
I have tried the below sql query
select ffl.user_function_name, ff.function_name, rtl.responsibility_name
from apps.fnd_form_functions ff,
apps.fnd_form_functions_tl ffl,
apps.fnd_responsibility_vl rtl,
apps.fnd_responsibility r,
apps.fnd_compiled_menu_functions cmf
where cmf.function_id = ff.function_id
and r.menu_id = cmf.menu_id
and rtl.responsibility_id = r.responsibility_id
and cmf.grant_flag = 'Y'
and ff.function_id = ffl.function_id
and ffl.user_function_name = ffl.user_function_name
and rtl.responsibility_name like "responsibility name"
and ffl.language = 'US'
order by ffl.user_function_name;
I expected the sql results will be the only duplicate functions in the responsibility name with value responsibility name.
You need a group by with having count(*) > 1 clause
select ffl.user_function_name, ff.function_name, rtl.responsibility_name
from apps.fnd_form_functions ff
join apps.fnd_form_functions_tl ffl on ffl.function_id = ff.function_id
join apps.fnd_compiled_menu_functions cmf on cmf.function_id = ff.function_id
join apps.fnd_responsibility r on r.menu_id = cmf.menu_id
join apps.fnd_responsibility_vl rtl on rtl.responsibility_id = r.responsibility_id
where cmf.grant_flag = 'Y'
and ffl.user_function_name = ffl.user_function_name
and rtl.responsibility_name = 'responsibility name'
and ffl.language = 'US'
group by ffl.user_function_name, ff.function_name, rtl.responsibility_name
having count(*) > 1
order by ffl.user_function_name
and keep using ANSI-92 SQL standard.
I have a table I called Eventos. I have to select the corresponding outTime from the alarm which has the greater inTime.
And I have to do it quickly/optimized. I have about 1 million entries in the table.
This is my code:
SELECT
CadGrupoEventos.Severidade AS Nível,
CadGrupoEquipamentos.Nome AS Grupo,
CadEquipamentos.TAG AS Equipamento,
CadEventos.MensagemPT AS 'Mensagem de alarme',
MAX(Eventos.InTime) AS 'Hora do evento',
Eventos.OutTime AS 'Hora de saída'
FROM
CadGrupoEventos,
CadEquipamentos,
CadEventos,
Eventos,
CadUsuarios,
CadGrupoEquipamentos
WHERE
Eventos.Acked = 0
AND CadGrupoEventos.Codigo = CadEventos.Grupo
AND CadEquipamentos.Codigo = Eventos.TAG
AND CadEventos.Codigo = Eventos.CodMensagem
AND CadGrupoEquipamentos.Codigo = CadEquipamentos.Grupo
GROUP BY
CadGrupoEventos.Severidade,
CadEquipamentos.TAG,
CadEventos.MensagemPT,
CadGrupoEquipamentos.Nome,
Eventos.OutTime
This code, as it is, returns every single entry from the table.
I have to take Eventos.OutTime out of GROUP BY and still get the value of it.
This is just an educated guess based on your description. Notice I used ANSI-92 style joins which are much more explicit. I also used aliases to make this a lot more legible. Your query might look something like this.
select x.Severidade AS Nível,
x.Nome AS Grupo,
x.TAG AS Equipamento,
x.MensagemPT AS [Mensagem de alarme],
x.[Hora do evento],
x.OutTime AS [Hora de saída]
from
(
SELECT cge.Severidade,
cgequip.Nome,
ce.TAG,
cevt.MensagemPT,
MAX(e.InTime) AS [Hora do evento],
e.OutTime
, RowNum = ROW_NUMBER() over(partition by cge.Severidade, ce.TAG, cevt.MensagemPT, cgequip.Nome order by e.OutTime /*maybe desc???*/)
FROM CadGrupoEventos cge
join CadEventos cevt on cge.Codigo = cevt.Grupo
join Eventos e on AND cevt.Codigo = e.CodMensagem
join CadEquipamentos ce on ce.Codigo = e.TAG
join CadGrupoEquipamentos cgequip on cgequip.Codigo = ce.Grupo
cross join CadUsuarios cu --not sure if this is really what you want but your original code did not have any logic for this table
WHERE e.Acked = 0
GROUP BY cge.Severidade,
ce.TAG,
cevt.MensagemPT,
cgequip.Nome,
e.OutTime
) x
where x.RowNum = 1
I need to add a subquery to a join, because one payment can have more than one allotment, so I only need to account for the first match (where rownum = 1).
However, I'm not sure if adding pmt from the outer query to the subquery on the allotment join is best.
Should I be doing this differently in the event of performance hits, etc.. ?
SELECT
pmt.payment_uid,
alt.allotment_uid,
FROM
payment pmt
/* HERE: is the reference to pmt.pay_key and pmt.client_id
incorrect in the below subquery? */
INNER JOIN allotment alc ON alt.allotment_uid = (
SELECT
allotment_uid
FROM
allotment
WHERE
pay_key = pmt.pay_key
AND
pay_code = 'xyz'
AND
deleted = 'N'
AND
client_id = pmt.client_id
AND
ROWNUM = 1
)
WHERE
AND
pmt.deleted = 'N'
AND
pmt.date_paid >= TO_DATE('2017-07-01')
AND
pmt.date_paid < TO_DATE('2017-10-01') + 1;
It's difficult to identify the performance issue in your query without seeing an explain plan output. You query does seem to do an additional SELECT on the allotment for every record from the main query.
Here is a version which doesn't use correlated sub query. Obviously I haven't been able to test it. It does a simple join in and then filters all records except one of the allotments. Hope this helps.
WITH v_payment
AS
(
SELECT
pmt.payment_uid,
alt.allotment_uid,
ROW_NUMBER () OVER(PARTITION BY allotment_id) r_num
FROM
payment pmt JOIN allotment alt
ON (pmt.pay_key = alt.pay_key AND
pmt.client_id = alt.client_id)
WHERE pmt.deleted = 'N' AND
pmt.date_paid >= TO_DATE('2017-07-01') AND
pmt.date_paid < TO_DATE('2017-10-01') + 1 AND
alt.pay_code = 'xyz' AND
alt.deleted = 'N'
)
SELECT payment_uid,
allotment_uid
FROM v_payment
WHERE r_num = 1;
Let's know how this performs!
You can phrase the query that way. I would be more likely to do:
SELECT . . .
FROM payment p INNER JOIN
(SELECT a.*,
ROW_NUMBER() OVER (PARTITION BY pay_key, client_id
ORDER BY allotment_uid
) as seqnum
FROM allotment a
WHERE pay_code = 'xyz' AND deleted = 'N'
) a
ON a.pay_key = p.pay_key AND a.client_id = p.client_id AND
seqnum = 1
WHERE p.deleted = 'N' AND
p.date_paid >= DATE '2017-07-01' AND
p.date_paid < (DATE '2017-10-01') + 1;
I'm trying to write a SQL query to find duplicates. What I can't manage to do is to make my query only select duplicates where one of the columns value must differ. So, I want to find all the duplicates where all the columns are the same, but one of the values must differ.
What I've got at the moment:
SELECT
a.1, underlag.1, f.1, f.2, f.3, f.4, f.5, f.6, f.7, f.8,
COUNT(*) TotalCount
FROM
f
JOIN
a ON a.Id = f.Id
JOIN
underlag ON underlag.Id = f.Id
GROUP BY
a.1, underlag.1, f.1, f.2, f.3, f.4, f.5, f.6, f.7, f.8
HAVING
COUNT(*) > 1
ORDER BY
underlag.1
The column that I want to differ is f.9 but I've no clue on how to do this. Any help or pointers in the right direction would be great!
SELECT *
FROM (
SELECT
a1 = a.[1]
, underlag1 = underlag.[1]
, f.[1], f.[2], f.[3], f.[4], f.[5], f.[6], f.[7], f.[8], f.[9]
, val = SUM(1) OVER (PARTITION BY CHECKSUM(f.[1], f.[2], f.[3], f.[4], f.[5], f.[6], f.[7], f.[8]))
FROM f
JOIN a on a.Id = f.Id
JOIN underlag on underlag.Id = f.Id
) t
WHERE t.val > 1
ORDER BY underlag1
create table1 as SELECT from c.Name, Value, Qtr, Value as SUM(Value)
from User.Pofile a,pet_dsa_qtr_table b,User.Count c,User.Service d
WHERE Category = 'PROFESSIONAL' and Item_Name = 'PROF_PKT_RECVD' and
convert(char(32),d.User_Id) = c.Name and Service_Name_Cd = 2
and Status = 2 and d.User_Id *= a.User_Id and c.Period = b.Period
and Module = 'ACCT_TRADES' and Type in ('EQ','OPTN')
GROUP BY Name, Item_Value,
Qtr HAVING SUM(Value) >= 10000 and Item_Value in ('0', NULL);
The above was a query that was created by me as an equivalent for sybase.Can anyone help me in correcting this query
You have some quite serious syntax inconsistencies in your query which I have tried to correct (with guesswork as you haven't provided a table structure). e.g. In the select list you select "Value" but in the GROUP BY you group on "Item_Value" etc.
You also need to fully qualify your columns, some you qualify, some (like "Module" and "Type" etc) you don't.
You might also want to add a storage clause too.
Here is my best educated guess at what you are trying to achieve:
CREATE TABLE table1
AS
SELECT c.Name,
Item_Value,
Qtr,
SUM(Value) as "SUM_Value"
FROM User.Pofile a
pet_dsa_qtr_table b,
User.Count c,
User.Service d
WHERE Category = 'PROFESSIONAL'
AND Item_Name = 'PROF_PKT_RECVD'
AND TO_CHAR(d.User_Id) = c.Name
AND Service_Name_Cd = 2
AND Status = 2
AND d.User_Id = a.User_Id(+)
AND c.Period = b.Period
AND Module = 'ACCT_TRADES'
AND Type in ('EQ','OPTN')
GROUP BY c.Name,
Item_Value,
Qtr
HAVING (SUM(Value) >= 10000
AND NVL(Item_Value, '0') = '0');