In my database i have the following rows and columns: https://i.imgur.com/ktUZY9d.jpg
My problem is the same employee has 3 different departments, but he is currently only active in 1. How do I change this SQL statement to only include the latest department he is in, which started in 2018 and ends in 2100, as seen by the ALLOCATION_START and ALLOCATION_END?
Query
string agentIdSubQuery = "SELECT DISTINCT " +
"AGENT_ID " +
"FROM " +
"KS_DRIFT.V_AGENT_ALLOCATION " +
"WHERE " +
"LENGTH(AGENT_INITIALS) < 5";
if(queryParams.SnapshotDate.HasValue)
agentIdSubQuery += " AND " + OracleConversion.ToOracleDate(queryParams.SnapshotDate) + " BETWEEN ALLOCATION_START AND ALLOCATION_END";
Update:
Tried alot of different solutions, but it crashes everytime, when i run through the debugger, further Down in this method this Query is causing me to crash:
string sql = "SELECT " +
"age1.* " +
"FROM " +
"KS_DRIFT.V_AGENT_ALLOCATION age1 " +
"INNER JOIN " +
"(" + agentIdSubQuery + ") age2 ON age1.AGENT_ID = age2.AGENT_ID " +
"ORDER BY " +
"AGENT_INITIALS";
Error Message:
{"Error occured during execution of SQL query: SELECT age1.* FROM KS_DRIFT.V_AGENT_ALLOCATION age1 INNER JOIN (SELECT max(DISTINCT AGENT_ID FROM KS_DRIFT.V_AGENT_ALLOCATION WHERE LENGTH(AGENT_INITIALS) < 5 AND '2018-08-15' BETWEEN ALLOCATION_START AND ALLOCATION_END AND (UPPER(AGENT_INITIALS) = 'JKKA')) age2 ON age1.AGENT_ID = age2.AGENT_ID ORDER BY AGENT_INITIALS."}
Also giving me an inner exception:
{"ORA-00904: \"AGE2\".\"AGENT_ID\": ugyldig identifikator"}
Debugging error screeenshot
Order it by the newest start date (descending) and select Top 1!
string agentIdSubQuery = "AGENT_ID " +
"FROM " +
"KS_DRIFT.V_AGENT_ALLOCATION " +
"WHERE " +
"LENGTH(AGENT_INITIALS) < 5 " +
" AND ROWNUM = 1 " +
" ORDER BY ALLOCATION_START DESC";
EDIT, changed Top 1 to Rownum = 1, for Oracle syntax
The table V_AGENT_ALLOCATION contains various departments per agent along with the dates the agent worked there. You want an agent's last department, which you get with Oracle's KEEP LAST. You haven't given us much information on your table, though. Let's say that the department is referenced by an allocation_id:
select
agent_id,
max(id_allocation) keep (dense_rank last order by allocation_start)
as id_current_allocation
from v_agent_allocation
group by agent_id
order by agent_id;
Your error message shows the final generated SQL:
{"Error occurred during execution of SQL query: SELECT age1.* FROM KS_DRIFT.V_AGENT_ALLOCATION age1 INNER JOIN (SELECT max(DISTINCT AGENT_ID FROM KS_DRIFT.V_AGENT_ALLOCATION WHERE LENGTH(AGENT_INITIALS) < 5 AND '2018-08-15' BETWEEN ALLOCATION_START AND ALLOCATION_END AND (UPPER(AGENT_INITIALS) = 'JKKA')) age2 ON age1.AGENT_ID = age2.AGENT_ID ORDER BY AGENT_INITIALS."}
If you format that so that it's readable, you get:
select age1.*
from ks_drift.v_agent_allocation age1
inner join
( select max(distinct agent_id
from ks_drift.v_agent_allocation
where length(agent_initials) < 5
and '2018-08-15' between allocation_start and allocation_end
and (upper(agent_initials) = 'JKKA') ) age2
on age1.agent_id = age2.agent_id
order by agent_initials
Two syntax issues should jump out:
There is a missing closing bracket after max(distinct agent_id (the distinct is also redundant)
The date literal is missing its date keyword - it should be date '2018-08-15' (or better still, a bind variable).
The brackets around (upper(agent_initials) = 'JKKA') are redundant but perhaps they arise from your generator logic and it's easiest to keep them.
I'm not sure how that relates to your 'newest allocated department' requirement, though. Some sample data (not a screenshot) would help.
If you're looking for the current department, you should compare the allocation dates with the current date.
Your query already has this WHERE clause, so it should work just fine for the example provided. But if you might want to specify that you need only ONE row using the ROWNUM special variable clause (assuming it's Oracle).
SELECT DISTINCT AGENT_ID
FROM KS_DRIFT.V_AGENT_ALLOCATION
WHERE LENGTH(AGENT_INITIALS) < 5
AND ALLOCATION_START < CURRENT_DATE AND CURRENT_DATE < ALLOCATION_END
AND ROWNUM = 1
I am writing this query that I want to transition into C# but I get an error.
The error:
Incorrect syntax near the keyword 'SELECT'.
Incorrect syntax near 'Products'.
Here is the query I am trying to run.
Select
[ID]
,[ProductTypeID]
,[SeriesID]
,[PartNumber]
,[Title]
,[SEOFriendlyURLTitle]
,[HTMLDescription]
,[HTMLValueAdded]
,[RoHSCompliant]
,[ULCompliant]
,[CECompliant]
,[Series]
,[BUSINESS_UNIT]
,[PACKAGING_TYPE]
,[PACK_QTY]
,[MOQ]
,[ORDER_MULTIPLE]
,[LEAD_TIME_WEEKS]
,[INTERNATIONAL_HARMONIZE_CODE]
,[ECCN_NUMBER]
,[COUNTRY_OF_ORIGIN]
,[IS_PART_STATIC_SENSITIVE]
,[IS_PART_LEAD_PB_FREE]
,[MOISTURE_SENSITIVITY_LEVEL_MSL]
,[REGISTERABLE]
,[TAPE_WIDTH]
,[TAPE_MATERIAL]
,[QtyOnHand]
,[QtyOnSalesOrder]
,[QtyOnBackOrder]
,[ProductLine]
,[Reach138Compliant]
,[ConflictMinerals]
,[WebEnabled]
,[DateAdded]
,[UpdateDate]
,[Reviewed]
,[ReviewedBy]
,[Deleted]
,[Book]
,[CustomSort]
,[ONEK]
,[FIVEK]
,[TENK]
,[TWENTYFIVEK]
,[Fifty]
,[OneHundred]
,[FiveHundred]
FROM Products.Products
Join
(SELECT Products.Prices.ProductID,
Max(IIf(Products.Prices.Code='ONEK',Products.Prices.Price,Null)) AS ONEK,
Max(IIf(Products.Prices.Code='FIVEK',Products.Prices.Price,Null)) AS FIVEK,
Max(IIf(Products.Prices.Code='TENK',Products.Prices.Price,Null)) AS TENK,
Max(IIf(Products.Prices.Code='TWENTYFIVEK',Products.Prices.Price,Null)) AS TWENTYFIVEK,
Max(IIf(Products.Prices.Code='Fifty',Products.Prices.Price,Null)) AS Fifty,
Max(IIf(Products.Prices.Code='OneHundred',Products.Prices.Price,Null)) AS OneHundred,
Max(IIf(Products.Prices.Code='FiveHundred',Products.Prices.Price,Null)) AS FiveHundred
FROM Products.Prices
GROUP BY Products.Prices.ProductID
) As pp
ON Products.Products.ID = pp.ProductID
Here is the query in C#:
y1.CommandText = "Select [ID], [PartNumber], [Book], [HTMLDescription], [HTMLValueAdded], [RoHSCompliant], [ULCompliant],[CECompliant], [Series], [BUSINESS_UNIT], [ONEK], [FIVEK], [TENK], [TWENTYFIVEK]" +
",[Fifty], [OneHundred], [FiveHundred], [PACKAGING_TYPE], [PACK_QTY], [MOQ], [ORDER_MULTIPLE], [LEAD_TIME_WEEKS], [INTERNATIONAL_HARMONIZE_CODE], [ECCN_NUMBER], [COUNTRY_OF_ORIGIN]" +
",[IS_PART_STATIC_SENSITIVE], [IS_PART_LEAD_PB_FREE], [MOISTURE_SENSITIVITY_LEVEL_MSL], [REGISTERABLE], [TAPE_WIDTH], [TAPE_MATERIAL], [Reach138Compliant], [ConflictMinerals], [WebEnabled]" +
"FROM Products.Products" +
"Join" +
"(SELECT Products.Prices.ProductID," +
"Max(IIf(Products.Prices.Code='ONEK',Products.Prices.Price,Null)) AS ONEK," +
"Max(IIf(Products.Prices.Code='FIVEK',Products.Prices.Price,Null)) AS FIVEK," +
"Max(IIf(Products.Prices.Code='TENK',Products.Prices.Price,Null)) AS TENK," +
"Max(IIf(Products.Prices.Code='TWENTYFIVEK',Products.Prices.Price,Null)) AS TWENTYFIVEK," +
"Max(IIf(Products.Prices.Code='Fifty',Products.Prices.Price,Null)) AS Fifty," +
"Max(IIf(Products.Prices.Code='OneHundred',Products.Prices.Price,Null)) AS OneHundred," +
"Max(IIf(Products.Prices.Code='FiveHundred',Products.Prices.Price,Null)) AS FiveHundred" +
"FROM Products.Prices" +
"GROUP BY Products.Prices.ProductID" +
") As pp" +
"ON Products.Products.ID = pp.ProductID" +
"where partnumber like '6%'";
Please help and thank you.
Take this segment as an example:
"FROM Products.Products" +
"Join" +
When these strings are concatenated, you get:
"FROM Products.ProductsJoin"
You need to include the spaces.
"FROM Products.Products " +
"Join" +
You are missing SPACES in front of FROM, Join, (SELECT etc... So when they are being output you are seeing FROM Products.ProductsJoin. You also want to prefix with # to protect against escaping issue. To fix you want:
y1.CommandText = #"Select [ID], [PartNumber], [Book], [HTMLDescription], [HTMLValueAdded], [RoHSCompliant], [ULCompliant],[CECompliant], [Series], [BUSINESS_UNIT], [ONEK], [FIVEK], [TENK], [TWENTYFIVEK]" +
",[Fifty], [OneHundred], [FiveHundred], [PACKAGING_TYPE], [PACK_QTY], [MOQ], [ORDER_MULTIPLE], [LEAD_TIME_WEEKS], [INTERNATIONAL_HARMONIZE_CODE], [ECCN_NUMBER], [COUNTRY_OF_ORIGIN]" +
",[IS_PART_STATIC_SENSITIVE], [IS_PART_LEAD_PB_FREE], [MOISTURE_SENSITIVITY_LEVEL_MSL], [REGISTERABLE], [TAPE_WIDTH], [TAPE_MATERIAL], [Reach138Compliant], [ConflictMinerals], [WebEnabled]" +
" FROM Products.Products" +
" Join" +
" (SELECT Products.Prices.ProductID," +
"Max(IIf(Products.Prices.Code='ONEK',Products.Prices.Price,Null)) AS ONEK," +
"Max(IIf(Products.Prices.Code='FIVEK',Products.Prices.Price,Null)) AS FIVEK," +
"Max(IIf(Products.Prices.Code='TENK',Products.Prices.Price,Null)) AS TENK," +
"Max(IIf(Products.Prices.Code='TWENTYFIVEK',Products.Prices.Price,Null)) AS TWENTYFIVEK," +
"Max(IIf(Products.Prices.Code='Fifty',Products.Prices.Price,Null)) AS Fifty," +
"Max(IIf(Products.Prices.Code='OneHundred',Products.Prices.Price,Null)) AS OneHundred," +
"Max(IIf(Products.Prices.Code='FiveHundred',Products.Prices.Price,Null)) AS FiveHundred" +
" FROM Products.Prices" +
" GROUP BY Products.Prices.ProductID" +
") As pp" +
" ON Products.Products.ID = pp.ProductID" +
" where partnumber like '6%'";
Just use verbatim string (#), copy your query and create it like:
string query =
#"Select
[ID]
,[ProductTypeID]
,[SeriesID]
,[PartNumber]
,[Title]
,[SEOFriendlyURLTitle]
,[HTMLDescription]
,[HTMLValueAdded]
,[RoHSCompliant]
,[ULCompliant]
,[CECompliant]
,[Series]
,[BUSINESS_UNIT]
,[PACKAGING_TYPE]
,[PACK_QTY]
,[MOQ]
,[ORDER_MULTIPLE]
,[LEAD_TIME_WEEKS]
,[INTERNATIONAL_HARMONIZE_CODE]
,[ECCN_NUMBER]
,[COUNTRY_OF_ORIGIN]
,[IS_PART_STATIC_SENSITIVE]
,[IS_PART_LEAD_PB_FREE]
,[MOISTURE_SENSITIVITY_LEVEL_MSL]
,[REGISTERABLE]
,[TAPE_WIDTH]
,[TAPE_MATERIAL]
,[QtyOnHand]
,[QtyOnSalesOrder]
,[QtyOnBackOrder]
,[ProductLine]
,[Reach138Compliant]
,[ConflictMinerals]
,[WebEnabled]
,[DateAdded]
,[UpdateDate]
,[Reviewed]
,[ReviewedBy]
,[Deleted]
,[Book]
,[CustomSort]
,[ONEK]
,[FIVEK]
,[TENK]
,[TWENTYFIVEK]
,[Fifty]
,[OneHundred]
,[FiveHundred]
FROM Products.Products
Join
(SELECT Products.Prices.ProductID,
Max(IIf(Products.Prices.Code='ONEK',Products.Prices.Price,Null)) AS ONEK,
Max(IIf(Products.Prices.Code='FIVEK',Products.Prices.Price,Null)) AS FIVEK,
Max(IIf(Products.Prices.Code='TENK',Products.Prices.Price,Null)) AS TENK,
Max(IIf(Products.Prices.Code='TWENTYFIVEK',Products.Prices.Price,Null)) AS TWENTYFIVEK,
Max(IIf(Products.Prices.Code='Fifty',Products.Prices.Price,Null)) AS Fifty,
Max(IIf(Products.Prices.Code='OneHundred',Products.Prices.Price,Null)) AS OneHundred,
Max(IIf(Products.Prices.Code='FiveHundred',Products.Prices.Price,Null)) AS FiveHundred
FROM Products.Prices
GROUP BY Products.Prices.ProductID
) As pp
ON Products.Products.ID = pp.ProductID";
(This will save you from figuring out errors in your concatenation, and would be more readable IMO)
I'm populating a DataTable in C# using an OleDbDataAdapter, and I am trying to get a query to work without much success.
The communication to/from the server works fine, as is evidenced by the simple query that returns all the records without any filter:
var commandText = string.Format("SELECT IsoShtRevID, LineID, Filename, Revision " +
"FROM dbo.PDSIsometricSheets WHERE SchemaName='{0}'", projectNo);
This gives me a list of about 8000 entries, however there is some redundancy.
There are multiple rows with the same LineID, but each one has a separate Revision value. I'm trying to get only the rows with the highest revision for each LineID, from a range of 0 to 5.
Here are a few of the attempts I've tried so far:
var commandText = string.Format("SELECT * FROM
(SELECT max(Revision) as LatestRev
FROM dbo.PDSIsometricSheets)
WHERE Revision < 5" , projectNo);
var commandText = string.Format("SELECT T.IsoShtRevID, T.LineID, T.Filename, T.Revision
FROM dbo.PDSIsometricSheets T
WHERE Revision =
(SELECT MAX(T1.Revision)
FROM dbo.PDSIsometricSheets T1
WHERE T1.IsoShtRevID = T.IsoShtRevID
)", projectNo);
var commandText = string.Format("SELECT IsoShtRevID, LineID, Filename, MAX(Revision) as LatestRevision
FROM dbo.PDSIsometricSheets WHERE SchemaName='{0}'
GROUP BY LineID, IsoShtRevID, Filename", projectNo);
Here are the questions I've visited so far trying to get this to work:
SQL Select only rows with Max Value on a Column
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
Fetch the row which has the Max value for a column
Select Rows with Maximum Column Value group by Another Column
Everything above either returns the same thing as my original query, or just errors out from bad syntax. SQL is the furthest thing from my forte, and I'm trying to figure out if I'm limited in functionality by using a DataAdapter.
UPDATE:
Here's the latest iteration, using some advice from below:
var commandText = string.Format("SELECT IsoShtRevID, LineID, Filename, MAX(Revision) as MaxRevision " +
"FROM dbo.PDSIsometricSheets " +
"WHERE SchemaName='{0}' AND Revision <= 5 AND Revision >= 0" +
"GROUP BY IsoShtRevID, LineID, Filename", projectNo);
This filters out the revision to values between 0 and 5, however there are still multiple rows for LineID, each with different Revision numbers. It's like the Max command is being ignored...
Option 3 should work but if it doesn't is because FileName or IsoShtRevID change across Revisions. In that case, you can do this:
SELECT a.IsoShtRevID ,
a.LineID ,
a.Filename ,
a.Revision
FROM dbo.PDSIsometricSheets a
join (select max(Revision) as Revision, LineID
from dbo.PDSIsometricSheets where SchemaName ='{0}' ) x
join a on a.Revision = x.Revision and a.LineID=x.LineID
WHERE a.SchemaName = '{0}'
Finally got it thanks to the comments, reading more SQL, and viewing my commandstring diligently at runtime for typos.
var commandText = string.Format("SELECT T1.IsoShtRevID, T1.LineID, T1.FileName, T1.Revision " +
"FROM dbo.PDSIsometricSheets T1 " +
"INNER JOIN (" +
"SELECT LineID, MAX(Revision) as MaxRevision " +
"FROM dbo.PDSIsometricSheets " +
"WHERE SchemaName='{0}' AND Revision <= 5 AND Revision >= 0" +
"GROUP BY LineID" +
") T2 " +
"ON T1.LineID = T2.LineID AND T1.Revision = T2.MaxRevision ", projectNo);