Issue in sql server with join query - sql-server

I have four tables for join I am trying to join with views in sql server. i have successfully done join query and retrieving data from multiple table with join query. But I Execute the same query sql server shows the different result every time.
SELECT DISTINCT
dbo.tbl_verifyFinger2.ID
, dbo.tbl_verifyCnicDetails.fID
, dbo.tbl_verifyCnicDetails.colGRName
, dbo.tbl_verifyFinger2.colCompanyID
, dbo.tbl_verifyAvailableFingers.colCNIC
, dbo.tbl_agent.agent_id
, dbo.tbl_agent.colIMSI
, dbo.tbl_verifyFinger2.colDate
, dbo.tbl_verifyFinger2.colStatusMessage
FROM dbo.tbl_verifyFinger2
INNER JOIN dbo.tbl_verifyCnicDetails
ON dbo.tbl_verifyFinger2.ID = dbo.tbl_verifyCnicDetails.fID
INNER JOIN dbo.tbl_verifyAvailableFingers
ON dbo.tbl_verifyFinger2.colCNIC = dbo.tbl_verifyAvailableFingers.colCNIC
INNER JOIN dbo.tbl_agent
ON dbo.tbl_verifyAvailableFingers.colIMSI = dbo.tbl_agent.colIMSI

Cause SQL Server not allow to use ORDER By clause inside views, to get same preview of result every time, you must include ORDER BY clause in you outer SELECT query, at the end of query.
Of course, carefully choose columns in ORDER BY clause, because it must be deterministic which guarantee that every time sorted result will be the same and moving your rows up and down will not be presented more.
SELECT
*
FROM schema_name.view_name AS v
ORDER BY
v.column_name (ASC|DESC) --If ommiting directions, ASC is the default

Related

SQL Server - select a commonly named column over multiple joined tables where the last edit date is most recent

Our County recently purchased a new real-estate system. I have created a view that joins over a dozen tables. (assessment, taxpayer, collections, etc...)
Every table has a last change data and last change user field.
We would like to know when a parcel number was last changed in the system and what login made those changes.
I was able to pull the most recent change data by using the following nested query...
SELECT
... ,
(SELECT MAX(v)
FROM (VALUES (table1.last_chg_datetime), (table2.last_chg_datetime),
(table3.last_chg_datetime), (table4.last_chg_datetime), ... ,
(tableN.last_chg_datetime)) AS value(v)) AS last_chg_datetime
FROM table1
LEFT OUTER JOIN table2 ...
What is the best way to also pull the last changed user from the table that corresponds with the last changed date?
I am sure this could be done with a stored procedure. I was just wondering if this could also be extracted by altering the nested query?
We are running SQL Server 2016.
The query could be rewritten as:
SELECT ... ,sub. *
FROM table1
LEFT OUTER JOIN table2 ...
OUTER APPLY (SELECT TOP 1 *
FROM (VALUES (table1.last_chg_datetime, table1.user), (table2.last_chg_datetime, table2.user),
(table3.last_chg_datetime, table3.user), (table4.last_chg_datetime, table4.user), ... ,
(tableN.last_chg_datetime, tableN.user)) AS value(v, user_name)
ORDER BY v DESC
) sub;
It could be also extended by table name:
(VALUES ('table1', table1.last_chg_datetime, table1.user),
('table2', table2.last_chg_datetime, table2.user), ...
) AS value(table_name, v, user_name)

SQL Server Using sub query in JOIN statements

Does JOINING of tables more easy to read or faster to execute if I create a sub query and a select statement with only the columns needed for the entire query?
-- Example
SELECT s.Id,
s.TransactionDate,
s.TransactionNo,
s.CustomerId,
s.SiteLocationId,
s.SubTotal,
sd.ItemId,
sd.UnitPrice,
sd.GrossAmount
FROM tblTransactions s
LEFT OUTER JOIN tblTransactionDetails sd ON sd.TransactionId = s.Id
Compare to this:
SELECT s.Id,
s.TransactionDate,
s.TransactionNo,
s.CustomerId,
s.SubTotal,
sd.ItemId,
sd.UnitPrice,
sd.GrossAmount
FROM tblTransactions s
LEFT OUTER JOIN (
SELECT TransactionId,
ItemId,
UnitPrice,
GrossAmount
FROM tblTransactionDetails
) sd ON sd.TransactionId = s.Id
What are the advantages and disadvantages of each example given? I am also trying to reduce the percentage read of the Details in the Execution Plan.
I think that SQL Server creates the same execution plan for both queries. If you want to increase the performance due to the column selection, you should create a non-clustered index. Then, the query optimizer should use the more compact index instead the table.
CREATE NONCLUSTERED INDEX ix_tblTransactionDetails_test
ON tblTransactionDetails (TransactionId) INCLUDE (ItemId, UnitPrice, GrossAmount)

SQL Query is taking infinite time when using with order by

Below is my SQL Query
select top(10) ClientCode
FROM (((Branch INNER JOIN BusinessLocation ON
Branch.BranchCode=BusinessLocation.BranchCode)
INNER JOIN Center ON BusinessLocation.LocationCode = Center.LocationCode)
INNER JOIN Groups ON Center.CenterCode = Groups.CenterCode)
INNER JOIN Client ON Groups.GroupCode = Client.GroupCode
WHERE
((Client.CBStatus) IS NULL) AND ((Branch.PartnerName) in
('SVCL','Edelweiss'))
order by Client.ClientCode DESC
When i run it without order by it runs fine , but with order by it is not finishing execution. Why is this behavior ?
When you select using TOP statement, calculations and joins for every row are not necessarily calculated. When you try to order, at least one cell for all rows need to be calculated. It is a long query because your table is large and the behavior is not faulty. Don't let the fast running query without the order by mislead you about the complexity of your second query.
You can create an index on clientcode column. That would speed things up.

Is it possible to perform a join in Access on a second column if the first is blank?

I have this ugly source data with two columns, let's call them EmpID and SomeCode. Generally EmpID maps to the EmployeeListing table. But sometimes, people are entering the Employee IDs in the SomeCode field.
The person previously running this report in Excel 'solved' this problem by performing multiple vlookups with if statements, as well as running some manual checks to ensure results were accurate. As I'm moving these files to Access I am not sure how best to handle this scenario.
Ideally, I'm hoping to tell my queries to do a Left Join on SomeCode if EmpID is null, otherwise Left Join on EmpID
Unfortunately, there's no way for me to force validation or anything of the sort in the source data.
Here's the full SQL query I'm working on:
SELECT DDATransMaster.Fulfillment,
DDATransMaster.ConfirmationNumber,
DDATransMaster.PromotionCode,
DDATransMaster.DirectSellerNumber,
NZ([DDATransMaster]![DirectSellerNumber],[DDATransMaster]![PromotionCode]) AS EmpJoin,
EmployeeLookup.ID AS EmpLookup,
FROM FROM DDATransMaster
LEFT JOIN EmployeeLookup ON NZ([DDATransMaster]![DirectSellerNumber],[DDATransMaster]![PromotionCode]) = EmployeeLookup.[Employee #])
You can create a query like this:
SELECT
IIf(EmpID Is Null, SomeCode, EmpID) AS join_field,
field2,
etc
FROM YourTable
Or if the query will always be used within an Access session, Nz is more concise.
SELECT
Nz(EmpID, SomeCode) AS join_field,
field2,
etc
FROM YourTable
When you join that query to your other table, the Access query designer can represent the join between join_field and some matching field in the other table. If you were to attempt the IIf or Nz as part of the join's ON clause, the query designer can't display the join correctly in Design View --- it could still work, but may not be as convenient if you're new to Access SQL.
See whether this SQL gives you what you want.
SELECT
dda.Fulfillment,
dda.ConfirmationNumber,
dda.PromotionCode,
dda.DirectSellerNumber,
NZ(dda.DirectSellerNumber,dda.PromotionCode) AS EmpJoin,
el.ID AS EmpLookup
FROM
DDATransMaster AS dda
LEFT JOIN EmployeeLookup AS el
ON NZ(dda.DirectSellerNumber,dda.PromotionCode) = el.[Employee #])
But I would use the Nz part in a subquery.
SELECT
sub.Fulfillment,
sub.ConfirmationNumber,
sub.PromotionCode,
sub.DirectSellerNumber,
sub.EmpJoin,
el.ID AS EmpLookup
FROM
(
SELECT
Fulfillment,
ConfirmationNumber,
PromotionCode,
DirectSellerNumber,
NZ(DirectSellerNumber,PromotionCode) AS EmpJoin
FROM DDATransMaster
) AS sub
LEFT JOIN EmployeeLookup AS el
ON sub.EmpJoin = el.[Employee #])
What about:
LEFT JOIN EmployeeListing ON NZ(EmpID, SomeCode)
as your join, nz() uses the second parameter if the first is null, I'm not 100% sure this sort of join works in access. Worth 20 seconds to try though.
Hope it works.
You Could use a Union:
SELECT DDATransMaster.Fulfillment,
DDATransMaster.ConfirmationNumber,
DDATransMaster.PromotionCode,
DDATransMaster.DirectSellerNumber,
EmployeeLookup.ID AS EmpLookup
FROM DDATransMaster
LEFT JOIN EmployeeLookup ON
DDATransMaster.DirectSellerNumber = EmployeeLookup.[Employee #]
where DDATransMaster.DirectSellerNumber IS NOT NULL
Union
SELECT DDATransMaster.Fulfillment,
DDATransMaster.ConfirmationNumber,
DDATransMaster.PromotionCode,
DDATransMaster.DirectSellerNumber,
EmployeeLookup.ID AS EmpLookup
FROM DDATransMaster
LEFT JOIN EmployeeLookup ON
DDATransMaster.PromotionCode = EmployeeLookup.[Employee #]
where DDATransMaster.DirectSellerNumber IS NULL;

SQL Server Rewriting Left Join

I was having a problem with a larger query in SQL Server which I traced back to this section of code which isn't performing as expected.
SELECT item_name,item_num,rst_units
FROM tbl_item left join tbl_sales_regional on item_num=rst_item
WHERE rst_month=7 and rst_customer='AB123'
The first table (tbl_item) has 10,000 records. The second table (tbl_sales_regional) has 83 for the shown criteria.
Instead of returning 10,000 records with 9,917 nulls, the execution plan shows SQL Server has rewritten as an inner join and consequently returns 83 results.
In order to achieve the intended result, I have to join off a subquery. Can someone provide an explanation why this doesn't work?
Not sure which fields belong where, but you seem to have some fields from tbl_sales_regional in your WHERE condition.
Move them into the ON clause:
SELECT item_name, item_num, rst_units
FROM tbl_item
LEFT JOIN
tbl_sales_regional
ON rst_item = item_num
AND rst_month = 7
AND rst_customer = 'AB123'
The WHERE clause operates on the results of the join so these conditions cannot possibly hold true for any NULL records from tbl_sales_regional returned by the join, as NULL cannot be equal to anything.
That's why the optimizer transforms your query into the inner join.
Any conditions you have in your WHERE clause are applied regardless of the left join, effectively making it an inner join.
You need to change it to:
SELECT item_name,item_num,rst_units
FROM tbl_item left join tbl_sales_regional on item_num=rst_item
AND rst_month=7 and rst_customer='AB123'

Resources