why the external fields canĀ“t be used in these subquery?
SELECT d1_cod,
D1_VUNIT,
(
SELECT sd2.d1_vunit from (select d1_filial,d1_vunit,d1_emissao,d1_cod,d1_doc)
FROM sd1160 sd12
WHERE sd12.D1_EMISSAO < **x.d1_emissao**
And sd12.D1_FILIAL = **x.d1_filial**
And sd12.D1_COD = **x.d1_cod**
And sd12.D_E_L_E_T_ = ' '
ORDER BY sd12.d1_emissao DESC)
Where ROWNUM < 2)
FROM sd1160 x
WHERE x.D_E_L_E_T_ = ' '
AND x.d1_emissao = '20160808'
ORDER BY x.d1_emissao DESC
)
Thanks
Oracle only recognizes correlated references one-level deep. One way around this is to use the keep syntax:
SELECT d1_cod,
D1_VUNIT,
(SELECT MAX(st12.d1_vunit) KEEP (DENSE_RANK FIRST ORDER BY sd12.d1_emissao DESC)
FROM sd1160 sd12
WHERE sd12.D1_EMISSAO < **x.d1_emissao** AND
sd12.D1_FILIAL = **x.d1_filial** AND
sd12.D1_COD = **x.d1_cod** AND
sd12.D_E_L_E_T_ = ' '
)
FROM sd1160 x
WHERE x.D_E_L_E_T_ = ' ' AND x.d1_emissao = '20160808'
ORDER BY x.d1_emissao DESC;
Related
select so.nombre + ' ' + so.apellidos as nombre_completo,
se.actividad,
ss.fecha as fecha
from Soldado so, Servicio se, ServicioSoldado ss
where ss.soldadoID = so.soldadoID and ss.servicioID = se.servicioID
group by so.nombre, so.apellidos, se.actividad, ss.fecha, so.soldadoID
order by so.soldadoID, ss.fecha desc
This is the table I have
And this is the output I would like to get:
Try this:
WITH DataSource AS
(
select so.nombre + ' ' + so.apellidos as nombre_completo,
se.actividad,
ss.fecha as fecha,
ROW_NUMBER() OVER (PARTITION BY so.soldadoID ORDER BY ss.fecha desc) AS [RowID]
from Soldado so
INNER JOIN Servicio se
ON so.soldadoID = ss.soldadoID
INNER JOIN ServicioSoldado ss
ON ss.servicioID = se.servicioID
)
SELECT *
FROM DataSource
WHERE [RowID] = 1;
The idea is to use ROW_NUMBER to create an order set of records for each user and the to get the first (the latest) one only for each user.
Im trying to use the Over Partition to create a row number based on SupplierAccountNumber then Sort by DateTimeCreated and then only show record 1. my current script i get an error saying Invalid column name 'RowNum'??
I have a list of email addresses for suppliers which have multiple addresses, i only want to pick out the most recent email address. Is there a better way of doing it?
SELECT plsuppliercontact.plsuppliercontactid,
plsupplieraccount.supplieraccountnumber,
plsupplieraccount.supplieraccountname,
plsupplieraccount.supplieraccountshortname,
plsuppliercontactvalue.contactvalue,
syscontacttype.name,
Rownum = Row_number()
OVER(
partition BY plsupplieraccount.supplieraccountnumber
ORDER BY plsuppliercontactvalue.datetimecreated DESC)
FROM alops.dbo.plsupplieraccount PLSupplierAccount,
alops.dbo.plsuppliercontact PLSupplierContact,
alops.dbo.plsuppliercontactvalue PLSupplierContactValue,
alops.dbo.syscontacttype SYSContactType
WHERE plsupplieraccount.plsupplieraccountid =
plsuppliercontact.plsupplieraccountid
AND plsuppliercontactvalue.plsuppliercontactid =
plsuppliercontact.plsuppliercontactid
AND syscontacttype.syscontacttypeid =
plsuppliercontactvalue.syscontacttypeid
AND (( syscontacttype.name = 'E-mail Address' ))
AND rownum = 1;
You didn't specify with RDBMS you were using, but most of them only apply aliases after the query is executed.
One trick is to wrap the query in an another query that takes care of this condition. E.g.:
SELECT *
FROM (
SELECT plsuppliercontact.plsuppliercontactid,
plsupplieraccount.supplieraccountnumber,
plsupplieraccount.supplieraccountname,
plsupplieraccount.supplieraccountshortname,
plsuppliercontactvalue.contactvalue,
syscontacttype.name,
Rownum = Row_number()
OVER(
partition BY plsupplieraccount.supplieraccountnumber
ORDER BY plsuppliercontactvalue.datetimecreated DESC)
FROM alops.dbo.plsupplieraccount PLSupplierAccount,
alops.dbo.plsuppliercontact PLSupplierContact,
alops.dbo.plsuppliercontactvalue PLSupplierContactValue,
alops.dbo.syscontacttype SYSContactType
WHERE plsupplieraccount.plsupplieraccountid =
plsuppliercontact.plsupplieraccountid
AND plsuppliercontactvalue.plsuppliercontactid =
plsuppliercontact.plsuppliercontactid
AND syscontacttype.syscontacttypeid =
plsuppliercontactvalue.syscontacttypeid
AND (( syscontacttype.name = 'E-mail Address' ))
)
WHERE rownum = 1;
Use the MAX aggregate
SELECT plsuppliercontact.plsuppliercontactid,
plsupplieraccount.supplieraccountnumber,
plsupplieraccount.supplieraccountname,
plsupplieraccount.supplieraccountshortname,
plsuppliercontactvalue.contactvalue,
syscontacttype.name,
MAX(plsuppliercontactvalue.datetimecreated)
FROM alops.dbo.plsupplieraccount PLSupplierAccount,
alops.dbo.plsuppliercontact PLSupplierContact,
alops.dbo.plsuppliercontactvalue PLSupplierContactValue,
alops.dbo.syscontacttype SYSContactType
WHERE plsupplieraccount.plsupplieraccountid =
plsuppliercontact.plsupplieraccountid
AND plsuppliercontactvalue.plsuppliercontactid =
plsuppliercontact.plsuppliercontactid
AND syscontacttype.syscontacttypeid =
plsuppliercontactvalue.syscontacttypeid
AND (( syscontacttype.name = 'E-mail Address' ))
GROUP BY plsuppliercontact.plsuppliercontactid,
plsupplieraccount.supplieraccountnumber,
plsupplieraccount.supplieraccountname,
plsupplieraccount.supplieraccountshortname,
plsuppliercontactvalue.contactvalue,
syscontacttype.name
I'm working with FileNet. I'm trying to get the folders that a document may be filed in to appear in one column of the record set delimited with semicolons. This was the layout previously decided on and I am tasked with making Oracle do it. Here's what I have for a query so far:
SELECT d1.F_DOCNUMBER,
d1.F_DOCCLASSNUMBER,
d1.F_ENTRYDATE,
d1.F_ARCHIVEDATE,
d1.F_RETENTBASE,
d1.F_RETENTDISP,
d1.F_RETENTOFFSET,
d1.F_PAGES,
d1.F_DOCTYPE,
d1.F_DOCFORMAT,
d1.A32 AS CERT_NUM,
d1.A35 AS DOC_TYPE,
d1.A36 AS BATCH_KEY,
d1.A37 AS FIELD_REP_CODE,
d1.A38 AS EFFECTIVE_DATE,
d1.A39 AS VOUCH_NUM_HIGH,
d1.A40 AS VOUCH_NUM_LOW,
f1.Folders
FROM doctaba d1
LEFT JOIN (SELECT SUBSTR (SYS_CONNECT_BY_PATH (F_FOLDERNAME , ';'), 2) Folders
FROM (SELECT fc2.F_DOCNUMBER, f2.F_FOLDERNAME, ROW_NUMBER () OVER (ORDER BY f2.F_FOLDERNAME) rn, COUNT (*) OVER () cnt
FROM folder_contents fc2
INNER JOIN folder f2
ON f2.F_FOLDERNUMBER = fc2.F_FOLDERNUMBER
WHERE fc2.F_DOCNUMBER = d1.F_DOCNUMBER)
WHERE rn = cnt
START WITH rn = 1
CONNECT BY rn = PRIOR rn + 1) f1
ON d1.F_DOCNUMBER = f1.F_DOCNUMBER
WHERE d1.F_DOCTYPE IS NULL
AND d1.F_DOCNUMBER >= 107777
AND d1.F_DOCNUMBER <= 305791
ORDER BY d1.F_DOCNUMBER;
The problem is that d1.F_DOCNUMBER is being marked as an invalid identifier. I read on some forums that Oracle may not let that column identifier work multiple query levels down. Anyone have some suggestions on how to make this work? Thanks!
EDIT:
Here's my original query that just includes the folder values in rows.
SELECT doctaba.F_DOCNUMBER,
doctaba.F_DOCCLASSNUMBER,
doctaba.F_ENTRYDATE,
doctaba.F_ARCHIVEDATE,
doctaba.F_RETENTBASE,
doctaba.F_RETENTDISP,
doctaba.F_RETENTOFFSET,
doctaba.F_PAGES,
doctaba.F_DOCTYPE,
doctaba.F_DOCFORMAT,
doctaba.A32 AS CERT_NUM,
doctaba.A35 AS DOC_TYPE,
doctaba.A36 AS BATCH_KEY,
doctaba.A37 AS FIELD_REP_CODE,
doctaba.A38 AS EFFECTIVE_DATE,
doctaba.A39 AS VOUCH_NUM_HIGH,
doctaba.A40 AS VOUCH_NUM_LOW,
folder.F_FOLDERNAME
FROM doctaba
LEFT JOIN folder_contents
ON doctaba.F_DOCNUMBER = folder_contents.F_DOCNUMBER
INNER JOIN folder
ON folder.F_FOLDERNUMBER = folder_contents.F_FOLDERNUMBER
WHERE doctaba.F_DOCTYPE IS NULL
AND doctaba.F_DOCNUMBER >= 107777
AND doctaba.F_DOCNUMBER <= 17208174
ORDER BY doctaba.F_DOCNUMBER;
In this case, you are lucky. You are only getting one value from the subquery, so you can just make it a correlated subquery in the select clause:
SELECT . . .
(SELECT SUBSTR(SYS_CONNECT_BY_PATH (F_FOLDERNAME , ';'), 2) as Folders
FROM (SELECT fc2.F_DOCNUMBER, f2.F_FOLDERNAME,
ROW_NUMBER () OVER (ORDER BY f2.F_FOLDERNAME) rn,
COUNT (*) OVER () cnt
FROM folder_contents fc2 INNER JOIN
folder f2
ON f2.F_FOLDERNUMBER = fc2.F_FOLDERNUMBER
WHERE fc2.F_DOCNUMBER = d1.F_DOCNUMBER
)
WHERE rn = cnt
START WITH rn = 1
CONNECT BY rn = PRIOR rn + 1
) as Folders
FROM doctaba d1
WHERE d1.F_DOCTYPE IS NULL AND
d1.F_DOCNUMBER >= 107777 AND
d1.F_DOCNUMBER <= 305791
ORDER BY d1.F_DOCNUMBER;
I am new to SQL so bear with me. I am returning data from multiple tables. Followed is my SQL (let me know if there is a better approach):
SELECT [NonScrumStory].[IncidentNumber], [NonScrumStory].[Description], [DailyTaskHours].[ActivityDate], [Application].[AppName], [SupportCatagory].[Catagory], [DailyTaskHours].[PK_DailyTaskHours],n [NonScrumStory].[PK_NonScrumStory]
FROM [NonScrumStory], [DailyTaskHours], [Application], [SupportCatagory]
WHERE ([NonScrumStory].[UserId] = 26)
AND ([NonScrumStory].[PK_NonScrumStory] = [DailyTaskHours].[NonScrumStoryId])
AND ([NonScrumStory].[CatagoryId] = [SupportCatagory].[PK_SupportCatagory])
AND ([NonScrumStory].[ApplicationId] = [Application].[PK_Application])
AND ([NonScrumStory].[Deleted] != 1)
AND [DailyTaskHours].[ActivityDate] >= '1/1/1990'
ORDER BY [DailyTaskHours].[ActivityDate] DESC
This is what is being returned:
This is nearly correct. I only want it to return one copy of PK_NonScrumStory though and I can't figure out how. Essentially, I only want it to return one copy so one of the top two rows would not be returned.
You could group by the NonScrumStore columns, and then aggregate the other columns like this:
SELECT [NonScrumStory].[IncidentNumber],
[NonScrumStory].[Description],
MAX( [DailyTaskHours].[ActivityDate]),
MAX( [Application].[AppName]),
MAX([SupportCatagory].[Catagory]),
MAX([DailyTaskHours].[PK_DailyTaskHours]),
[NonScrumStory].[PK_NonScrumStory]
FROM [NonScrumStory],
[DailyTaskHours],
[Application],
[SupportCatagory]
WHERE ([NonScrumStory].[UserId] = 26)
AND ([NonScrumStory].[PK_NonScrumStory] = [DailyTaskHours].[NonScrumStoryId])
AND ([NonScrumStory].[CatagoryId] = [SupportCatagory].[PK_SupportCatagory])
AND ([NonScrumStory].[ApplicationId] = [Application].[PK_Application])
AND ([NonScrumStory].[Deleted] != 1)
AND [DailyTaskHours].[ActivityDate] >= '1/1/1990'
group by [NonScrumStory].[IncidentNumber], [NonScrumStory].[Description],[NonScrumStory].[PK_NonScrumStory]
ORDER BY 3 DESC
From the screenshot it seems DISTINCT should have solved your issue but if not you could use the ROW_NUMBER function.
;WITH CTE AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY [NonScrumStory].[PK_NonScrumStory] ORDER BY [DailyTaskHours].[ActivityDate] DESC) AS RowNum,
[NonScrumStory].[IncidentNumber], [NonScrumStory].[Description], [DailyTaskHours].[ActivityDate], [Application].[AppName], [SupportCatagory].[Catagory], [DailyTaskHours].[PK_DailyTaskHours],n [NonScrumStory].[PK_NonScrumStory]
FROM [NonScrumStory], [DailyTaskHours], [Application], [SupportCatagory]
WHERE ([NonScrumStory].[UserId] = 26)
AND ([NonScrumStory].[PK_NonScrumStory] = [DailyTaskHours].[NonScrumStoryId])
AND ([NonScrumStory].[CatagoryId] = [SupportCatagory].[PK_SupportCatagory])
AND ([NonScrumStory].[ApplicationId] = [Application].[PK_Application])
AND ([NonScrumStory].[Deleted] != 1)
AND [DailyTaskHours].[ActivityDate] >= '1/1/1990'
)
SELECT * FROM CTE WHERE RowNum = 1 ORDER BY [ActivityDate] DESC
I believe if you add DISTINCT to your query that should solve your problem. Like so
SELECT DISTINCT [NonScrumStory].[IncidentNumber], [NonScrumStory].[Description],...
I read this article, and i have the code in oracle, but I want to convert it to work on MySQL. In Oracle, i use the function rank, with four columns can eligible or not, how i can use this in mysql, or, it is not possible?
This is the code, I want select the most eligible line, every line can have 4 columns completed, I want to rank one of which has more data.
SELECT vlr,
data
INTO vn_vlr,
vd_data
FROM (SELECT a.*, rank() over (ORDER BY nvl(a.id_categoria, -1) DESC,
nvl(a.id_peso, -1) DESC,
nvl(a.id_faixa, -1) DESC,
nvl(a.sexo, ' ') DESC ) rank
FROM tab_regra_pagamento a
WHERE a.id_competicao = pidcompedticao
AND a.tipo = 'NORMAL'
AND a.data_vencimento > SYSDATE
AND nvl(a.id_categoria, vid_categoria) = vid_categoria
AND nvl(a.id_faixa, vid_faixa) = vid_faixa
AND nvl(a.id_peso, vid_peso) = vid_peso
AND nvl(a.sexo, vsexo) = vsexo)
WHERE rank = 1;
SELECT #rank := #rank + (#value <> value),
#value := value
FROM (
SELECT #rank := 0,
#value := -1
) vars,
mytable
ORDER BY
value
In you case, when you just need all copies of the first set of values:
SELECT vlr, data
FROM tab_regra_pagamento a
WHERE a.id_competicao = pidcompedticao
AND a.tipo = 'NORMAL'
AND a.data_vencimento > SYSDATE
AND (a.id_cetegoria, a.id_faixa, a.id_peso, a.sexo) =
(
SELECT ai.id_cetegoria, ai.id_faixa, ai.id_peso, ai.sexo
FROM tab_regra_pagamento ai
WHERE ai.id_competicao = pidcompedticao
AND ai.tipo = 'NORMAL'
AND ai.data_vencimento > SYSDATE
ORDER BY
a.id_cetegoria DESC, a.id_faixa DESC, a.id_peso DESC, a.sexo DESC
LIMIT 1
)