How to user 2 condition in an select statement? - sql

I want that select name and family of user in a table that User-Id (in this)
is FK in another table. my conditions are:
1.[User-Id](in this table) = [Resume-Owner-Id] in other table.
2.Row number is between 2 value that get from asp program.
I write below code. but this has error.
SELECT *
FROM (SELECT Family,
Name,
Row_number()
OVER(
ORDER BY [User-Id] DESC) AS RowNum
FROM [Members-Description-Tbl]) AS People
WHERE [User-Id] = (SELECT [Resume-Owner-Id]
FROM [Resume-Tbl])
AND ( RowNum BETWEEN #StartRowIndex + 1 AND #MaxRows );

This is your query:
Select *
From (select Family, Name,
ROW_NUMBER() OVER (ORDER BY [User-Id] desc) AS RowNum
from [Members-Description-Tbl]
) As People
Where [User-Id] = (select [Resume-Owner-Id]
from [Resume-Tbl]
) AND
RowNum between #StartRowIndex+1 and #MaxRows
Such a query could get many errors -- variables could be undefined, tables not present, columns not defined.
One potential error that stands out is the = in the where clause. If the subquery returns more than one row, it will generate an error. The simple solution is to use in instead of =.

Thanks for your answer Gordon Linoffred.
Thanks for your answer Pradeep.
That's right. Your answers are right. But my query rise previous error again. I read my query again and understand that I must write [People].RowNum or RowNum instead of [User-Id]. This works now. Thanks again. :)

Related

How to join in SQL-SERVER

I am trying to learn SQL-SERVER and I have created the below query:
WITH T AS
(
SELECT ROW_NUMBER() OVER(ORDER BY d.DIALOG_ID) as row_num, *
FROM test.db as d
INNER JOIN test.dbs as ds
ON d.DIALOG_ID = ds.DIALOG_ID
)
SELECT *
FROM T
WHERE row_num <=10;
I found that the only way to limit is with ROW_NUMBER().
Although when I try to run the join I have this error:
org.jkiss.dbeaver.model.sql.DBSQLException: SQL Error [8156] [S0001]: The column 'DIALOG_ID' was specified multiple times for 'T'.
The problem: In the WITH, you do SELECT * which gets all columns from both tables db and dbs. Both have a column DIALOG_ID, so a column by that name ends up twice in the result set of the WITH.
Although until here that is all allowed, it is not good practice: why have the same data twice?
Things go wrong when SQL Server has to determine what SELECT * FROM T means: it expands SELECT * to the actual columns of T, but it finds a duplicate column name, and then it refuses to continue.
The fix (and also highly recommended in general): be specific about the columns that you want to output. If T has no duplicate columns, then SELECT * FROM T will succeed.
Note that the even-more-pure variant is to also be specific about what columns you select from T. By doing that it becomes clear at a glance what the SELECT produces, instead of having to guess or investigate when you look at the query later on (or when someone else does).
The updated code would look like this (fill in your column names as we don't know them):
WITH T AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY d.DIALOG_ID) as row_num,
d.DIALOG_ID, d.SOME_OTHER_COL,
ds.DS_ID, ds.SOME_OTHER_COL_2
FROM test.db AS d
INNER JOIN test.dbs AS ds ON d.DIALOG_ID = ds.DIALOG_ID
)
SELECT row_num, DIALOG_ID, SOME_OTHER_COL, DS_ID, SOME_OTHER_COL_2
FROM T
WHERE row_num <= 10;
WITH T AS
(
SELECT ROW_NUMBER() OVER(ORDER BY d.DIALOG_ID) as row_num, d.*
FROM test.db as d
INNER JOIN test.dbs as ds
ON d.DIALOG_ID = ds.DIALOG_ID
)
SELECT *
FROM T
WHERE row_num <=10;

Find the second largest value with Groupings

In SQL Server, I am attempting to pull the second latest NOTE_ENTRY_DT_TIME (items highlighted in screenshot). With the query written below it still pulls the latest date (I believe it's because of the grouping but the grouping is required to join later). What is the best method to achieve this?
SELECT
hop.ACCOUNT_ID,
MAX(hop.NOTE_ENTRY_DT_TIME) AS latest_noteid
FROM
NOTES hop
WHERE
hop.GEN_YN IS NULL
AND hop.NOTE_ENTRY_DT_TIME < (SELECT MAX(hope.NOTE_ENTRY_DT_TIME)
FROM NOTES hope
WHERE hop.GEN_YN IS NULL)
GROUP BY
hop.ACCOUNT_ID
Data sample in the table:
One of the "easier" ways to get the Nth row in a group is to use a CTE and ROW_NUMBER:
WITH CTE AS(
SELECT Account_ID,
Note_Entry_Dt_Time,
ROW_NUMBER() OVER (PARTITION BY AccountID ORDER BY Note_Entry_Dt_Time DESC) AS RN
FROM dbo.YourTable)
SELECT Account_ID,
Note_Entry_Dt_Time
FROM CTE
WHERE RN = 2;
Of course, if an ACCOUNT_ID only has 1 row, then it will not be returned in the result set.
The OP's statement "The row will not always be 2." from the comments conflicts with their statement "I am attempting to pull the second latest NOTE_ENTRY_DT_TIME" in the question. At a best guess, this means that the OP has rows with the same date, that could be the "latest" date. If so, then would simply need to replace ROW_NUMBER with DENSE_RANK. Their sampple data, however, doesn't suggest this is the case.
You can use window functions:
select *
from (
select
n.*,
row_number() over(partition by account_id order by note_entry_dt_time desc) rn
from notes n
) t
where rn = 2

Ambiguous column name using row_number() without alias

I'm trying to implement pagination in a query that is built using information from a view, and I need to use the row_number() function over a column when I don't know which table it is from.
SELECT * FROM (
SELECT class.ID as ID, user.ID as USERID, row_number() over (ORDER BY
ID desc) as row_number FROM class, user
) out_q WHERE row_number > #startrow ORDER BY row_number
The problem is that I only have the result column name (ID or USERID) that came from a previous query. If I execute this query, it will raise the error 'Ambiguous column name "ID"'. Is there a way to specify that I'm referencing the column ID that is being selected and not from a different table?
Is it possible to specify an alias to the query result itself?
I have already tried the following,
SELECT TOP 30 * FROM (
SELECT *, row_number() over (ORDER BY ID desc) as row_number FROM(
SELECT class.ID as ID, user.ID as USERID FROM class, user
) in_q
) out_q WHERE row_number > #startrow ORDER BY row_number
It works, but the SGBD gets confused on which query plan it has to use, because of the small row goal present in the outer query and the big set of results returned by the inner query, when #startrow is a small number, the query executes in less than one second, when it is a big number the query takes minutes to execute.
Your problem is the id in the row_number itself. If you want a stable sort, then include both ids:
SELECT *
FROM (SELECT class.ID as ID, user.ID as USERID,
row_number() over (ORDER BY class.ID desc, user.id) as row_number
FROM class CROSS JOIN user
) out_q
WHERE row_number > #startrow
ORDER BY row_number;
I assume the cartesian product is intentional. Sometimes, this indicates an error in the query. In general, I would advise you to avoid using commas in the from clause. If you do want a cartesian product, then be explicit by using CROSS JOIN.
You could try using the option you already tried, then use the OPTIMIZE FOR hint.
OPTION ( OPTIMIZE FOR (#startrow = 100000) );
See a description of the hint in MSDN docs here: https://msdn.microsoft.com/en-us/library/ms181714.aspx.

how do you retrieve the latest value from an oracle table

I am tryin to get the latest value from an oracle table based on server name. I have the following sql:
SELECT T."Node",T."Timestamp",T."MAX_User_CPU_Pct", T."MAX_System_CPU_Pct"
FROM DW.KPX_CPU_DETAIL_HV T where T."Node"='serverA%' and T."Timestamp"=
(select max(P."Timestamp") from DW.KPX_CPU_DETAIL_HV P where P."Node"='serverA%')
it does not seem to be working, any ideas what I might be doing wrong here?
Try this, might actually be faster than the sub-select (even if it was correct):
SELECT T."Node",
T."Timestamp",
T."MAX_User_CPU_Pct",
T."MAX_System_CPU_Pct"
FROM (
SELECT p.*,
row_Number() over (partition by p."Node" order by p."Timestamp" desc) as rn
FROM DW.KPX_CPU_DETAIL_HV p
) t
where rn = 1;
SELECT T."Node",T."Timestamp",T."MAX_User_CPU_Pct", T."MAX_System_CPU_Pct"
FROM (SELECT * FROM DW.KPX_CPU_DETAIL_HV T where T."Node" like 'serverA%' ORDER BY T."Timestamp" DESC) T
WHERE ROWNUM = 1
this did it for me, not sure it is the best solution but working for now.

How to enumerate returned rows in SQL?

I was wondering if it would be possible to enumerate returned rows. Not according to any column content but just yielding a sequential integer index. E.g.
select ?, count(*) as usercount from users group by age
would return something along the lines:
1 12
2 78
3 4
4 42
it is for https://data.stackexchange.com/
try:
SELECT
ROW_NUMBER() OVER(ORDER BY age) AS RowNumber
,count(*) as usercount
from users
group by age
If it's Oracle, use rownum.
SELECT SOMETABLE.*, ROWNUM RN
FROM SOMETABLE
WHERE SOMETABLE.SOMECOLUMN = :SOMEVALUE
ORDER BY SOMETABLE.SOMEOTHERCOLUMN;
The final answer will entirely depend on what database you're using.
For MySql:
SELECT #row := #row + 1 as row FROM anytable a, (SELECT #row := 0) r
use rownumber function available in sql server
SELECT
ROW_NUMBER() OVER (ORDER BY columnNAME) AS 'RowNumber',count(*) as usercount
FROM users
How you'd do that depends on your database server. In SQL Server, you could use row_number():
select row_number() over (order by age)
, age
, count(*) as usercount
from users
group by
age
order by
age
But it's often easier and faster to use client side row numbers.
for Mysql
set #row:=0;
select #row:=#row+1 as row, a.* from table_name as a;
In contrast to majority of other answers, and in accordance of the actual OP question, to
enumerate returned rows (...) NOT according to any column content
but rather in the order of returned query, one could use a dummy ordinal variable to ORDER BY in an ROW_NUMBER function, e.g.
ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS row_num
where one could actually use anything as an argument to the SELECT-statement, like SELECT 100, SELECT ‘A’, SELECT NULL, etc..
This way, the row numbers will be enumerated in the same order the data was added to the table.