oracle sql query generating some unexected resutls - sql

I have an sql query in which I have table named attan for the attendance and column named
S_TIME in which I stored in time and out time with a setting a flag of in with I and for O
Now I am trying to get in time as well as out time using the flag. I have written a query but result from this query are making some wrong sense.
Here is my query
SELECT X.AC_NO, X.IN_TIME, Y.OUT_TIME, X.S_DTE, X.CHK_IN, Y.CHK_OUT
FROM (SELECT A.AC_NO, A.S_TIME IN_TIME, A.AC_CHECKTYPE CHK_IN, A.S_DTE
FROM ATTN A
WHERE A.AC_CHECKTYPE = 'I' AND A.S_DTE = :P_DTE) X,
(SELECT B.AC_NO, B.S_TIME OUT_TIME, B.AC_CHECKTYPE CHK_OUT
FROM ATTN B
WHERE B.AC_CHECKTYPE = 'O' AND B.S_DTE = :P_DTE) Y
WHERE X.AC_NO = Y.AC_NO(+)
Through this query I always get the number of records of the employees who are in and only get 2 number of reocrds with out time.
Whereas in table there are 234 number of emps who are in and 256 are out but results don't match the data.
Please any one help me if any problem in my query.

SUGGESTION:
Run the subselects and see if you're getting all the rows you expect, with and without the "A.S_DTE = :P_DTE" date filter:
SELECT A.AC_NO, A.S_TIME IN_TIME, A.AC_CHECKTYPE CHK_IN, A.S_DTE
FROM ATTN A
WHERE A.AC_CHECKTYPE = 'I' AND A.S_DTE = :P_DTE
My first guess is that maybe you have a datetime, and unless the hours/minutes/seconds match exactly, you won't get the row. You can use to_char() to have just the "date" portion in your "from":
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:204714700346328550
In any case, seeing what rows you do (and don't) get in the subqueries should show you what's wrong with the complete query.
Please post back what you find!

Related

Oracle BIP OOTB SQL returning ORA-01427: single-row subquery returns more than one row

I am facing ORA-01427: single-row subquery returns more than one row error in one of my report. The report was build by previous vendor and it is a big SQL which seems like was generated by some tool and used in the report. I am having a tough time to figure out what's wrong. All the sub queries are either using aggregate functions or ROWNUM = 1 to return 1 record.
Please see if you can give me any pointers to which part I need to focus on. I checked the log files generated by the BIP but it just narrowed down it to the dataset.
Due to large size of the file, I provide the SQL in this file:
SQL
You'll have to scan the query line by line and check all subqueries that do not select an aggregated function (e.g. MIN(..)) and don't contain the ROWNUM = 1 limitation.
Example
(
SELECT
( ko.extn_attribute_timestamp006 )
FROM
moo_ref_entities ko
WHERE
ko.extn_attribute_number001 = lea.id
AND ko.attribute_category = 'RenewalAndOtherOptions_c'
AND nvl(ko.extn_attribute_timestamp003, sysdate) >= sysdate
AND ko.extn_attribute_timestamp005 = (
SELECT
MIN(ko.extn_attribute_timestamp005)
FROM
moo_ref_entities ko
WHERE
ko.extn_attribute_number001 = lea.id
AND ko.attribute_category = 'RenewalAndOtherOptions_c'
AND nvl(ko.extn_attribute_timestamp003, sysdate) >= sysdate
)
) AS option1_exc,
This is a typical trap as you constrain the extn_attribute_timestamp005 with a MIN subquery, but if you have ties in the timestamps you get exact the error you observe.
Here's a SELECT nested in a SELECT list that isn't guaranteed to yield just one row.
(
SELECT FL.lookup_code
FROM fnd_lookups FL
,hz_organization_profiles HO1
WHERE ho1.party_id = LEA.extn_attribute_number010
AND FL.lookup_code = HO1.extn_attribute_char035
AND FL.lookup_type = 'FND_SALES_CATEGORY'
) AS Sales_Category
It wouldn't have been hard for somebody to INSERT something to that fnd_lookups table to make that subquery yield more than one row. You could go for AND ROWNUM=1 or SELECT MAX(FL.lookup_code) lookup_code to see if it helps.

why does this query not give me only the specified accounts?

Oracle SQL Developer
I expect to see:
In the subquery, I have that the rownumber be less than 2. When I run this query separately, it gives me 2 accounts. However, when I'm running the entire query, the list of account numbers just goes on! what's happening here?
SELECT m.acctno, i.intervalstartdate, d.name, i.intervalvalue
FROM endpoints E
JOIN meters m on m.acctid = e.acctid
LEFT JOIN intervaldata I ON I.acctid = M.acctid
LEFT JOIN endpointmodels EM ON EM.endpointmodelid=E.hwmodelid
LEFT JOIN datadefinitions D ON D.datadefinitionid = I.datadefinitionid
WHERE 1=1
AND E.statuscodeid = 8
AND m.FORM = 2
and exists
(
SELECT m2.acctno
from acct m2
where m2.acctno is not null
--and m2.acctno=m2.acctno
and rownum <= 2
)
AND D.datadefinitionid =7077
AND I.intervalstartdate BETWEEN '24-SEP-2017 00:00' and '25-SEP-2017 00:00'
--TRUNC(sysdate - 1) + interval '1' hour AND TRUNC(sysdate - 1) + interval
'24' hour
ORDER BY M.acctno, I.intervalstartdate, I.datadefinitionid
This query is supposed to give me 97 rows for each account. The data i'm reading, the interval values, are the data we report for each customer in 96 intervals. so Im expecting for 2 accounts for example, to get 194 rows. i want to test for 2 accounts now, but then i want to run for 50,000. so with 2, it's not even working. Just giving me millions of rows for two accounts. Basicaly, i think my row num line of code is being ignored. I can't use an in clause because i cant pass 50,000 accounts into there. so I used the exist operator.
Let me know!
I think the error is in trying to use and exists (...) clause. The exists predicate returns true if the subquery returns any rows at all. So, in your case, the result of exists will always be true, unless the table is empty. This means it has no effect whatsoever on the outer query. You need to use something like
inner join (SELECT m2.acctno
from acct m2
where m2.acctno is not null
--and m2.acctno=m2.acctno
and rownum <= 2) sub1
on sub1.acctno = m.acctno
to get what you want instead of and exists (...).
One obvious mistake is the date condition, where you require a date to be between two STRINGS. If you keep dates in string format, you will run into thousands of problems and bugs and you won't be able to fix them.
Do you understand that '25-APR-2008 00:00:00' is between '24-SEP-2017 00:00:00' and '25-SEP-2017 00:00:00', if you compare them alphabetically (as strings)?
The solution is to make sure the date column is in DATE (or TIMESTAMP) data type, and then to compare to dates, not to strings.
As an aside - this will not cause any errors, but it is still bad code - in the EXISTS condition you have a condition for ROWNUM <= 2. What do you think that will do? The subquery either returns at least one row (the first one will automatically have ROWNUM = 1) or it doesn't. The condition on ROWNUM in that subquery in the EXISTS condition is just garbage.

How to calculate portfolio performance in Access

I've found this question particularly hard to google as the search terms come up with matching results, but not what I'm looking for...
I am trying to calculate the performance of a stock over a given time period using MS Access.
Example Calculation:
01.01.2016 Price: 100.00
25.02.2016 Price: 110.00
Pseudo Code:
Performance = Ending Price/Starting Price - 1
As simple as this would be to calculate in Excel, I can't seem to get it done in MS Access. My attempt thus far already fails on the simple task to get the end date. The Failure message is:
"You tried to execute a query that does not include the specified
expression'MoPo_BM_ID'as part of an aggregate function"
UPDATE:
I found a website that included some code that creates the desired result. The example works fine, but I tried adapting it to my own situation but am getting the error message "At most one record can be returned by this subquery".
SELECT x.Mandat_ID, x.BeginPrice, x.EndPrice, ([EndPrice]-[BeginPrice])/[BeginPrice] AS RETURN
FROM (SELECT Mandat_ID,
(SELECT Value AS BeginDate
FROM tbl_AMSDB_IndexMFP AS P
WHERE (Mandat_ID = Mandat_ID)
AND (Date =
(SELECT MIN(Date) AS Expr1
FROM tbl_AMSDB_IndexMFP AS D
WHERE (Mandat_ID = Mandat_ID)))) AS BeginPrice,
(SELECT Value AS BeginDate
FROM tbl_AMSDB_IndexMFP AS P
WHERE (Mandat_ID = Mandat_ID)
AND (Date =
(SELECT MAX(Date) AS Expr1
FROM tbl_AMSDB_IndexMFP AS D
WHERE (Mandat_ID = Mandat_ID)))) AS EndPrice
FROM tbl_AMSDB_IndexMFP
GROUP BY Mandat_ID) AS x
WHERE Mandat_ID=6028;
How can I get it to show me one record?
To get the max date to work, you need to group by the other fields in the select. So your query becomes
SELECT
tbl_MoPo_BM.MoPo_BM_ID,
tbl_AMSDB_IndexMFP.Mandat_ID,tbl_MoPo_BM.Launch_Date,
Max([tbl_AMSDB_IndexMFP]![Date]) AS End_Date
FROM
tbl_AMSDB_IndexMFP
INNER JOIN tbl_MoPo_BM ON tbl_AMSDB_IndexMFP.Mandat_ID =
tbl_MoPo_BM.AMSDB_MoPo_Code
GROUP BY
tbl_MoPo_BM.MoPo_BM_ID,
tbl_AMSDB_IndexMFP.Mandat_ID,
tbl_MoPo_BM.Launch_Date,
WHERE (((tbl_MoPo_BM.MoPo_BM_ID)=107))
Without knowing what your value/price field(s) are, whether the Launch_Date is the start date and whether duplicate entries are in your indexMFP table I can't write the rest to give you the answer to your Pseudo Performance calculation.

Why my sql query is so slow in one database?

I am using sql server 2008 r2 and I have two database, which is one have 11.000 record and another is just 3000 record, when i do run this query
SELECT Right(rtrim(tbltransac.No_Faktur),6) as NoUrut,
tbltransac.No_Faktur,
tbltransac.No_FakturP,
tbltransac.Kd_Plg,
Tblcust.Nm_Plg,
GRANDTOTAL AS Total_Faktur,
tbltransac.Nm_Pajak,
tbltransac.Tgl_Faktur,
tbltransac.Tgl_FakturP,
tbltransac.Total_Distribusi
FROM Tblcust
INNER JOIN ViewGrandtotal AS tbltransac ON Tblcust.Kd_Plg = tbltransac.Kd_Plg
WHERE tbltransac.Kd_Trn = 'J'
and year(tbltransac.tgl_faktur)=2015
And ISNULL(tbltransac.No_OPJ,'') <> 'SHOP'
Order by Right(rtrim(tbltransac.No_Faktur),6) Desc
It takes me 1 minute 30 sec in my server (I query it using sql management tool) that have 3000 record but it only took 3 sec to do a query in my another server which is have 11000 record, whats wring with my database?
I've already tried to backup and restore my 3000 record database and restore it in my 11000 record server, it's faster.. took 30 sec to do a query, but it's still annoying if i compare to my 11000 record server. They are in the same spec
How this happend? what i should check? i check on event viewer, resource monitor or sql management log, i couldn't find any error or blocked connection. There is no wrong routing too..
Please help... It just happen a week ago, before this it was fine, and I haven't touch the server more than a month...
as already mentioned before, you have three issues in your query.
Just as an example, change the query to this one:
SELECT Right(rtrim(tbltransac.No_Faktur),6) as NoUrut,
tbltransac.No_Faktur,
tbltransac.No_FakturP,
tbltransac.Kd_Plg,
Tblcust.Nm_Plg,
GRANDTOTAL AS Total_Faktur,
tbltransac.Nm_Pajak,
tbltransac.Tgl_Faktur,
tbltransac.Tgl_FakturP,
tbltransac.Total_Distribusi
FROM Tblcust
INNER JOIN ViewGrandtotal AS tbltransac ON Tblcust.Kd_Plg = tbltransac.Kd_Plg
WHERE tbltransac.Kd_Trn = 'J'
and tbltransac.tgl_faktur BETWEEN '20150101' AND '20151231'
And tbltransac.No_OPJ <> 'SHOP'
Order by NoUrut Desc --Only if you need a sorted output in the datalayer
Another idea, if your viewGrandTotal is quite large, could be an pre-filtering of this table before you join it. Sometimes SQL Server doesn't get a good plan which needs some lovely touch to get him in the right direction.
Maybe this one:
SELECT Right(rtrim(vgt.No_Faktur),6) as NoUrut,
vgt.No_Faktur,
vgt.No_FakturP,
vgt.Kd_Plg,
tc.Nm_Plg,
vgt.Total_Faktur,
vgt.Nm_Pajak,
vgt.Tgl_Faktur,
vgt.Tgl_FakturP,
vgt.Total_Distribusi
FROM (SELECT Kd_Plg, Nm_Plg FROM Tblcust GROUP BY Kd_Plg, Nm_Plg) as tc -- Pre-Filter on just the needed columns and distinctive.
INNER JOIN (
-- Pre filter viewGrandTotal
SELECT DISTINCT vgt.No_Faktur, vgt.No_Faktur, vgt.No_FakturP, vgt.Kd_Plg, vgt.GRANDTOTAL AS Total_Faktur, vgt.Nm_Pajak,
vgt.Tgl_Faktur, vgt.Tgl_FakturP, vgt.Total_Distribusi
FROM ViewGrandtotal AS vgt
WHERE tbltransac.Kd_Trn = 'J'
and tbltransac.tgl_faktur BETWEEN '20150101' AND '20151231'
And tbltransac.No_OPJ <> 'SHOP'
) as vgt
ON tc.Kd_Plg = vgt.Kd_Plg
Order by NoUrut Desc --Only if you need a sorted output in the datalayer
The pre filtering could increase the generation of a better plan.
Another issue could be just the multi-threading. Maybe your query get a parallel plan as it reaches the cost threshold because of the 11.000 rows. The other query just hits a normal plan due to his lower rows. You can take a look at the generated plans by including the actual execution plan inside your SSMS Query.
Maybe you can compare those plans to get a clue. If this doesn't help, you can post them here to get some feedback from me.
I hope this helps. Not quite easy to give you good hints without knowing table structures, table sizes, performance counters, etc. :-)
Best regards,
Ionic
Note: first of all you should avoid any function in Where clause like this one
year(tbltransac.tgl_faktur)=2015
Here Aaron Bertrand how to work with date in Where clause
"In order to make best possible use of indexes, and to avoid capturing too few or too many rows, the best possible way to achieve the above query is ":
SELECT COUNT(*)
FROM dbo.SomeLogTable
WHERE DateColumn >= '20091011'
AND DateColumn < '20091012';
And i cant understand your logic in this piece of code but this is bad part of your query too
ISNULL(tbltransac.No_OPJ,'') <> 'SHOP'
Actually Null <> "Shop" in this case, so Why are you replace it to ""?
Thanks and good luck
Here is some recommendations:
year(tbltransac.tgl_faktur)=2015 replace this with tbltransac.tgl_faktur >= '20150101' and tbltransac.tgl_faktur < '20160101'
ISNULL(tbltransac.No_OPJ,'') <> 'SHOP' replace this with tbltransac.No_OPJ <> 'SHOP' because NULL <> 'SHOP'.
Order by Right(rtrim(tbltransac.No_Faktur),6) Desc remove this, because ordering should be done in presentation layer rather then in data layer.
Read about SARG arguments and predicates:
What makes a SQL statement sargable?
To write an appropriate SARG, you must ensure that a column that has
an index on it appears in the predicate alone, not as a function
parameter. SARGs must take the form of column inclusive_operator
or inclusive_operator column. The column name is alone
on one side of the expression, and the constant or calculated value
appears on the other side. Inclusive operators include the operators
=, >, <, =>, <=, BETWEEN, and LIKE. However, the LIKE operator is inclusive only if you do not use a wildcard % or _ at the beginning of
the string you are comparing the column to

Update table with combined field from other tables

I have a table with actions that are being due in the future. I have a second table that holds all the cases, including the due date of the case. And I have a third table that holds numbers.
The problems is as follows. Our system automatically populates our table with future actions. For some clients however, we need to change these dates. I wanted to create an update query for this, and have this run through our scheduler. However, I am kind of stuck at the moment.
What I have on code so far is this:
UPDATE proxima_gestion p
SET fecha = (SELECT To_char(d.f_ult_vencim + c.hrem01, 'yyyyMMdd')
FROM deuda d,
c4u_activity_dates c,
proxima_gestion p
WHERE d.codigo_cliente = c.codigo_cliente
AND p.n_expediente = d.n_expediente
AND d.saldo > 1000
AND p.tipo_gestion_id = 914
AND p.codigo_oficina = 33
AND d.f_ult_vencim > sysdate)
WHERE EXISTS (SELECT *
FROM proxima_gestion p,
deuda d
WHERE p.n_expediente = d.n_expediente
AND d.saldo > 1000
AND p.tipo_gestion_id = 914
AND p.codigo_oficina = 33
AND d.f_ult_vencim > sysdate)
The field fecha is the current action date. Unfortunately, this is saved as a char instead of date. That is why I need to convert the date back to a char. F_ult_vencim is the due date, and hrem01 is the number of days the actions should be placed away from the due date. (for example, this could be 10, making the new date 10 days after the due date)
Apart from that, there are a few more criteria when we need to change the date (certain creditors, certain departments, only for future cases and starting from a certain amount, only for a certain action type.)
However, when I try and run this query, I get the error message
ORA-01427: single-row subquery returns more than one row
If I run both subqueries seperately, I get 2 results from both. What I am trying to accomplish, is that it connects these 2 queries, and updates the field to the new value. This value will be different for every case, as every due date will be different.
Is this even possible? And if so, how?
You're getting the error because the first SELECT is returning more than one row for each row in the table being updated.
The first thing I see is that the alias for the table in UPDATE is the same as the alias in both SELECTs (p). So all of the references to p in the subqueries are referencing proxima_gestion in the subquery rather than the outer query. That is, the subquery is not dependent on the outer query, which is required for an UPDATE.
Try removing "proxima_gestion p" from FROM in both subqueries. The references to p, then, will be to the outer UPDATE query.