I have multiple join (left join) derived tables in my query and one of them returns an empty result set which gives me a problem in my WHERE clause.
WHERE Clause:
WHERE (ISNULL(BalanceThis.Balance,0) + ISNULL(RL.Balance,0) + ISNULL(OtherPayThis.Balance,0) + ISNULL(RUPBalThis.Balance,0)) <> 0
Query:
LEFT JOIN (
SELECT AE3.IDNo, SUM(ISNULL(AE3.Debit,0)) AS Debit, SUM(ISNULL(AE3.Credit,0)) AS Credit,
ABS(SUM(ISNULL(AE3.Debit,0))-SUM(ISNULL(AE3.Credit,0))) AS Balance
FROM AccountingEntries AE3 WITH (NOLOCK)
WHERE AE3.BookName NOT IN ('BFSL')
AND AE3.GLAccount = '1.03.01' AND ISNULL(AE3.TC,'') = 'LAC'
AND ((Datepart(MM,AE3.DateEntry)=Datepart(MM,#Date))
AND Datepart(YEAR,AE3.DateEntry)=Datepart(YEAR,#Date))
GROUP BY AE3.IDNo
) RL ON RL.IDNo = Loans.LoanID
Result set:
IDNo Debit Credit Balance
Is there a way to return a static result set whenever a derive table is empty by using ##ROWCOUNT?
like this:
IDNo Debit Credit Balance
EMP12 0 0 0
Thankss.
Here's one way to do what you want:
WITH MyQuery As
(
-- This is your original query
-- This returns no rows
SELECT 'I have no rows' As OriginalQuery WHERE 0=1
)
-- Select from your query
SELECT * FROM MyQuery
UNION ALL
-- If there's nothing in your query, UNION ALL this part
SELECT 'I only appear when there are no rows' WHERE NOT EXISTS (SELECT * FROM MyQuery)
Related
I have a MSSQL query:
SELECT Artikel.ArtikelID, Artikel.K_HerstellerName AS ManufacturerName, Artikel.K_HerstellerPN AS ManufacturerPN, Artikel.ArtikelNummer AS SupplierPN, Artikel.Bezeichnung + ' - ' + Artikel.LangText AS Description,
Artikel.LetzterEK AS Price, Artikel.IstGesperrt AS Gesperrt, Lager.Verfuegbar AS Quantity, Lager.LagerPlatz AS LP
FROM Artikel INNER JOIN
Lager ON Artikel.ArtikelID = Lager.ArtikelID
WHERE (Artikel.K_HerstellerPN <> '') AND (Artikel.IstGesperrt = 'False') AND (Artikel.ArtikelNummer LIKE '%[0-9]-[0-9]%')
Here you can see how it looks like: https://ibb.co/fyOHv9
How to SUM() appropriate rows in MSSQL query for column "Quantity"?
In result all rows must be unique.
you need to group by all the columns that make each row unique, then use aggregate functions in your select, for example:
SELECT
MIN(Artikel.ArtikelID ) ArtikelID,
MIN(Artikel.K_HerstellerName) ManufacturerName,
SUM(Lager.Verfuegbar) Quantity
FROM Artikel
INNER JOIN Lager ON Artikel.ArtikelID = Lager.ArtikelID
WHERE (Artikel.K_HerstellerPN <> '') ...
GROUP BY
Artikel.ArtikelID,
Artikel.K_HerstellerName,
...
First when I started this project seemed very simple. Two tables, field tbl1_USERMASTERID in Table 1 should be update from field tbl2_USERMASTERID Table 2. After I looked deeply in Table 2, there is no unique ID that I can use as a key to join these two tables. Only way to match the records from Table 1 and Table 2 is based on FIRST_NAME, LAST_NAME AND DOB. So I have to find records in Table 1 where:
tbl1_FIRST_NAME equals tbl2_FIRST_NAME
AND
tbl1_LAST_NAME equals tbl2_LAST_NAME
AND
tbl1_DOB equals tbl2_DOB
and then update USERMASTERID field. I was afraid that this can cause some duplicates and some users will end up with USERMASTERID that does not belong to them. So if I find more than one record based on first,last name and dob those records would not be updated. I would like just to skip and leave them blank. That way I wouldn't populate invalid USERMASTERID. I'm not sure what is the best way to approach this problem, should I use SQL or ColdFusion (my server side language)? Also how to detect more than one matching record?
Here is what I have so far:
UPDATE Table1 AS tbl1
LEFT OUTER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.fname = tbl2.fname
AND tbl1.lname = tbl2.lname
SET tbl1.usermasterid = tbl2.usermasterid
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
Here is query where I tried to detect duplicates:
SELECT DISTINCT
tbl1.FName,
tbl1.LName,
tbl1.dob,
COUNT(*) AS count
FROM Table1 AS tbl1
LEFT OUTER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.FName = tbl2.first
AND tbl1.LName = tbl2.last
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
AND LTRIM(RTRIM(tbl1.first)) <> ''
AND LTRIM(RTRIM(tbl1.last)) <> ''
AND LTRIM(RTRIM(tbl1.dob)) <> ''
GROUP BY tbl1.FName,tbl1.LName,tbl1.dob
Some data after I tested query above:
First Last DOB Count
John Cook 2008-07-11 2
Kate Witt 2013-06-05 1
Deb Ruis 2016-01-22 1
Mike Bennet 2007-01-15 1
Kristy Cruz 1997-10-20 1
Colin Jones 2011-10-13 1
Kevin Smith 2010-02-24 1
Corey Bruce 2008-04-11 1
Shawn Maiers 2016-08-28 1
Alenn Fitchner 1998-05-17 1
If anyone have idea how I can prevent/skip updating duplicate records or how to improve this query please let me know. Thank you.
You could check for and avoid duplicate matches using with common_table_expression (Transact-SQL)
along with row_number()., like so:
with cte as (
select
t.fname
, t.lname
, t.dob
, t.usermasterid
, NewUserMasterId = t2.usermasterid
, rn = row_number() over (partition by t.fname, t.lname, t.dob order by t2.usermasterid)
from table1 as t
inner join table2 as t2 on t.dob = t2.dob
and t.fname = t2.fname
and t.lname = t2.lname
and ltrim(rtrim(t.usermasterid)) = ''
)
--/* confirm these are the rows you want updated
select *
from cte as t
where t.NewUserMasterId != ''
and not exists (
select 1
from cte as i
where t.dob = i.dob
and t.fname = i.fname
and t.lname = i.lname
and i.rn>1
);
--*/
/* update those where only 1 usermasterid matches this record
update t
set t.usermasterid = t.NewUserMasterId
from cte as t
where t.NewUserMasterId != ''
and not exists (
select 1
from cte as i
where t.dob = i.dob
and t.fname = i.fname
and t.lname = i.lname
and i.rn>1
);
--*/
I use the cte to extract out the sub query for readability. Per the documentation, a common table expression (cte):
Specifies a temporary named result set, known as a common table expression (CTE). This is derived from a simple query and defined within the execution scope of a single SELECT, INSERT, UPDATE, or DELETE statement.
Using row_number() to assign a number for each row, starting at 1 for each partition of t.fname, t.lname, t.dob. Having those numbered allows us to check for the existence of duplicates with the not exists() clause with ... and i.rn>1
You could use a CTE to filter out the duplicates from Table1 before joining:
; with CTE as (select *
, count(ID) over (partition by LastName, FirstName, DoB) as IDs
from Table1)
update a
set a.ID = b.ID
from Table2 a
left join CTE b
on a.FirstName = b.FirstName
and a.LastName = b.LastName
and a.Dob = b.Dob
and b.IDs = 1
This will work provided there are no exact duplicates (same demographics and same ID) in table 1. If there are exact duplicates, they will also be excluded from the join, but you can filter them out before the CTE to avoid this.
Please try below SQL:
UPDATE Table1 AS tbl1
INNER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.fname = tbl2.fname
AND tbl1.lname = tbl2.lname
LEFT JOIN Table2 AS tbl3
ON tbl3.dob = tbl2.dob
AND tbl3.fname = tbl2.fname
AND tbl3.lname = tbl2.lname
AND tbl3.usermasterid <> tbl2.usermasterid
SET tbl1.usermasterid = tbl2.usermasterid
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
AND tbl3.usermasterid is null
I have a query in sql stored procedure. I want to get record from other query from its id how I do that.
SELECT t.Name ,t.CreatedDate ,t.CreatedBy , t.Amount
,t.Margin ,t.Probability ,t.Id
FROM (SELECT a = 1) a
CROSS JOIN
(SELECT
Name = HirschInternational_MSCRM.dbo.SalesOrderBase.Name
,CreatedDate=HirschInternational_MSCRM.dbo.SalesOrderBase.CreatedOn
,CreatedBy=HirschInternational_MSCRM.dbo.SystemUserBase.FullName
,Amount = totalamount
,Probability=CloseProbability
,Id=SalesOrderId
,Margin=(SELECT ( ISNULL( ((Sum(Price)-Sum(CurrentCost)) / NULLIF( Sum(Price), 0 ))*100, 0 ) )
FROM HirschInternational_MSCRM.dbo.ProductBase
JOIN HirschInternational_MSCRM.dbo.SalesOrderDetailBase
ON HirschInternational_MSCRM.dbo.SalesOrderDetailBase.ProductId = HirschInternational_MSCRM.dbo.ProductBase.ProductId
JOIN HirschInternational_MSCRM.dbo.SalesOrderBase
ON HirschInternational_MSCRM.dbo.SalesOrderBase.SalesOrderId = HirschInternational_MSCRM.dbo.SalesOrderDetailBase.SalesOrderId)
FROM HirschInternational_MSCRM.dbo.SalesOrderBase
JOIN HirschInternational_MSCRM.dbo.OpportunityBase
ON HirschInternational_MSCRM.dbo.SalesOrderBase.Opportunityid = HirschInternational_MSCRM.dbo.OpportunityBase.Opportunityid
JOIN HirschInternational_MSCRM.dbo.SystemUserBase
ON HirschInternational_MSCRM.dbo.SystemUserBase.SystemUserId = HirschInternational_MSCRM.dbo.SalesOrderBase.CreatedBy
WHERE YEAR(HirschInternational_MSCRM.dbo.SalesOrderBase.CreatedOn)=YEAR(GETDATE())
I want Margin from every record I want Output like
It's not entirely clear what you want, but you might be looking for something like
select *
from (your SQL SELECT statement goes here) t1
where id = ?;
I want to get margin of every record how I filter margin query for SalesOrderId
like
Margin=(SELECT ( ISNULL( ((Sum(Price)-Sum(CurrentCost)) / NULLIF( Sum(Price), 0 ))*100, 0 ) )
FROM HirschInternational_MSCRM.dbo.ProductBase
JOIN HirschInternational_MSCRM.dbo.SalesOrderDetailBase
ON HirschInternational_MSCRM.dbo.SalesOrderDetailBase.ProductId = HirschInternational_MSCRM.dbo.ProductBase.ProductId
JOIN HirschInternational_MSCRM.dbo.SalesOrderBase
ON HirschInternational_MSCRM.dbo.SalesOrderBase.SalesOrderId = HirschInternational_MSCRM.dbo.SalesOrderDetailBase.SalesOrderId
Where HirschInternational_MSCRM.dbo.SalesOrderBase.SalesOrderId= //SalesOrderId that I get in main query)
how I pass that SalesOrderId in this query
I have 2 Excel files which I imported into MS Access as two tables. These two tables are identical but imported on different dates.
Now, how can I find out what rows and what fields are updated on the later date? Any help would be highly appreciated.
Finding Inserted records is easy
select * from B where not exists (select 1 from A where A.pk=B.pk)
Finding Deleted records is just as easy
select * from A where not exists (select 1 from B where A.pk=B.pk)
Finding Updated records is a pain. The following rigorous query assumes you have nullable columns and it should work in all situations.
select B.*
from B
inner join A on B.pk=A.pk
where A.col1<>B.col1 or (IsNull(A.col1) and not IsNull(B.col1)) or (not IsNull(A.col1) and IsNull(B.col1))
or A.col2<>B.col2 or (IsNull(A.col2) and not IsNull(B.col2)) or (not IsNull(A.col2) and IsNull(B.col2))
or A.col3<>B.col3 or (IsNull(A.col3) and not IsNull(B.col3)) or (not IsNull(A.col3) and IsNull(B.col3))
etc...
If the columns are defined as NOT NULL then the query is much simper, just remove all the NULL tests.
If the columns are nullable but you can identify a value that will never appear in the data, then use a simple comparison like:
Nz(A.col1,neverAppearingValue)<>Nz(B.col1,neverAppearingValue)
I believe this should be as simple as running a query like this:
SELECT *
FROM Table1
JOIN Table2
ON Table1.ID = Table2.ID AND Table1.Date != Table2.Date
One way to do this is by unpivoting both tables, so you get a new table with , , . Note, though, that you have to take types into account.
For example, the following gets differences in fields:
with oldt as (select id, col, val
from <old table> t
unpivot (val for col in (<column list>)) unpvt
),
newt as (select id, col, val
from <new table> t
unpivot (val for col in (<column list>)) unpvit
)
select *
from oldt full outer join newt on oldt.id = newt.id
where oldt.id is null or newt.id is null
The alternative way with a join is rather cumbersome. This version shows whether columns are added, deleted, and which columns changed if any:
select *
from (select coalesce(oldt.id, newt.id) as id,
(case when oldt.id is null and newt.id is not null then 'ADDED'
when oldt.id is not null and newt.id is null then 'DELETED'
else 'SAME'
end) as stat,
(case when oldt.col1 <> newt.col1 or oldt.col1 is null and newt.col1 is null
then 1 else 0 end) as diff_col1,
(case when oldt.col2 <> newt.col2 or oldt.col2 is null and newt.col2 is null
then 1 else 0 end) as diff_col2,
...
from <old table> oldt full outer join <new table> newt on oldt.id = newt.id
) c
where status in ('ADDED', 'DELETED') or
(diff_col1 + diff_col2 + ... ) > 0
It does have the advantage of working for any data types.
(Select * from OldTable Except Select *from NewTable)
Union All
(Select * from NewTable Except Select *from OldTable)
I have a query where i'm selecting 50 ids from the DB and grouping them by the id.
The only problem is that only 34 exists in the DB so it only shows 34 results.
My desired result is to show 50 results with the ones that don't exists in.
Is this possible?
Thanks
My query
SELECT no, count(no) as visits FROM DB
WHERE (no = '1' or no = '2' or no = '3' or no = '4' or no = '5')
GROUP BY no
This example will only give me 3 records even though i'm selecting 5 records
with noTable
as
( select 1 as no
union
select 2
union
select 3
union
select 4
union
select 5
)
select noTable.no,count(*)
from noTable inner join DB
on noTable.no = DB.no group by noTable.no
union
select noTable.no,0
from noTable left join DB
on noTable.no = DB.no
where DB.no is null;
Might not be elegant if there're 50 id...
You could add a tally table using WITH and LEFT JOIN your original table with the tally table.
;with q (no) AS (
SELECT 1
UNION ALL
SELECT no + 1
FROM q
WHERE no < 50
)
SELECT q.no
, CASE WHEN db.no IS NOT NULL
THEN COUNT(q.no)
ELSE 0
END AS Visits
FROM q
LEFT JOIN db ON db.no = q.no
GROUP BY
no