Remove the duplicate rows in views (SQL Server 2014 management studio) - sql-server

I have 2 tables item and memo. In item, itemId is the PK and the itid is the FK. In memo the memID is the PK.
I created a view:
SELECT
dbo.memo.memID, dbo.memo.fullname, dbo.memo.company,
dbo.memo.department, dbo.memo.MRnum, dbo.memo.date,
dbo.memo.returndate, dbo.memo.remarks,
dbo.memo.issuedby, dbo.memo.picture, dbo.item.itemID AS Expr1,
dbo.item.Itemnumber, dbo.item.description, dbo.item.qty,
dbo.item.unitofmeasure, dbo.item.itid
FROM
dbo.memo
INNER JOIN
dbo.item ON dbo.memo.memID = dbo.item.itid
WHERE
(dbo.memo.department = N'tsd')
and output is this
this is the output
I just want 1 output of the fullname, company, department, MRnum, date , remarks, issuedby every multiple rows of item
enter image description here
Hope you understand . thank you

You can use DISTINCT in your query.
See below
SELECT DISTINCT dbo.memo.memID, dbo.memo.fullname, dbo.memo.company, dbo.memo.department, dbo.memo.MRnum, dbo.memo.date, dbo.memo.returndate, dbo.memo.remarks, dbo.memo.issuedby, dbo.memo.picture, dbo.item.itemID AS Expr1, dbo.item.Itemnumber, dbo.item.description, dbo.item.qty, dbo.item.unitofmeasure, dbo.item.itid
FROM dbo.memo
INNER JOIN dbo.item ON dbo.memo.memID = dbo.item.itid
WHERE (dbo.memo.department = N'tsd')

i just want , 1 output of the fullname, company, department, MRnum,
date , remarks, issuedby with multiple rows of item
You could do this, use group by on required columns and take top 1
SELECT TOP 1
dbo.memo.fullname ,
dbo.memo.company ,
dbo.memo.department ,
dbo.memo.MRnum ,
dbo.memo.date ,
dbo.memo.remarks ,
dbo.memo.issuedby
FROM dbo.memo
INNER JOIN dbo.item
ON dbo.memo.memID = dbo.item.itid
WHERE ( dbo.memo.department = N'tsd' )
GROUP BY dbo.memo.fullname ,
dbo.memo.company ,
dbo.memo.department ,
dbo.memo.MRnum ,
dbo.memo.date ,
dbo.memo.remarks ,
dbo.memo.issuedby

Also you can use TOP like below if you are certain you get all duplicate records.
SELECT TOP 1 dbo.memo.memID, dbo.memo.fullname, dbo.memo.company, dbo.memo.department, dbo.memo.MRnum, dbo.memo.date, dbo.memo.returndate, dbo.memo.remarks, dbo.memo.issuedby, dbo.memo.picture, dbo.item.itemID AS Expr1, dbo.item.Itemnumber, dbo.item.description, dbo.item.qty, dbo.item.unitofmeasure, dbo.item.itid
FROM dbo.memo
INNER JOIN dbo.item ON dbo.memo.memID = dbo.item.itid
WHERE (dbo.memo.department = N'tsd')

Related

T-SQL multiple subqueries with JOIN and MAX(date)

I have this query with 2 LEFT JOINS each with a sub-query.
The sub-queries should select the row with the latest date PointsChangeDate__c for a specific campaign e.g: PointsTypeCode__c = '1'.
Problem is that it is choosing what appears to be just random dates.
If I run just one JOIN / sub-query, then the result is correct, but when I add the 2nd JOIN / sub-query, then the results are incorrect and it seems to be pulling random dates.
I suspect my issue is with the type of JOIN I am using, but I cannot see why, because if I LEFT JOIN, then I am including all results (a._ContactKey) pulled from the first query and carrying that all the way through.
SELECT
a._ContactKey ContactId,
a.Full_Name_1__c Full_Name,
a.MC_Phone__c Mobile,
a.POSCustomerNumber__c POS_Customer_Number,
a.POSCustomerStatus__c POSCustomerStatus,
'IL' Locale,
a.Mobile_1__c Mobile_for_text,
g.TotalPoints__c TotalPoints_SourceMethod_1,
g.ValidUntil__c ValidUntil_SourceMethod_1,
g.date_1 PointsChangeDate__c_1,
h.TotalPoints__c TotalPoints_SourceMethod_2,
h.ValidUntil__c ValidUntil_SourceMethod_2,
h.date_2 PointsChangeDate__c_2
FROM
Contact_Salesforce AS a
LEFT JOIN
(SELECT
Contact__c,
TotalPoints__c,
ValidUntil__c,
MAX(PointsChangeDate__c) date_1
FROM
Member_points__c_Salesforce
WHERE
PointsTypeCode__c = '1'
GROUP BY Contact__c , TotalPoints__c , ValidUntil__c, PointsChangeDate__c) AS g ON a._ContactKey = g.Contact__c
LEFT JOIN
(SELECT Contact__c,
TotalPoints__c,
ValidUntil__c,
MAX(PointsChangeDate__c) date_2
FROM
Member_points__c_Salesforce
WHERE
PointsTypeCode__c = '2'
GROUP BY Contact__c , TotalPoints__c , ValidUntil__c, PointsChangeDate__c) AS h ON h.Contact__c = g.Contact__c
LEFT JOIN
SMS_Unsubscribe AS c ON REPLACE(CONCAT('972',
RIGHT(RTRIM(LTRIM(a.Mobile_1__c)), 9)),
'-',
'') = c.Mobile
LEFT JOIN
Member_Segments__c_Salesforce AS b ON b.Contact__c = a._ContactKey
WHERE
a.Mobile_1__c IS NOT NULL
AND c.Mobile IS NULL
AND a.POSCustomerStatus__c = '0'
AND b.IsActive__c = 'true'
GROUP BY a._ContactKey , a.Full_Name_1__c , a.MC_Phone__c , a.POSCustomerNumber__c , a.POSCustomerStatus__c , Locale , a.Mobile_1__c , a.Mobile_1__c , b.SegmentTypeID__c, b.SegmentTypeDescription__c , b.ToDate__c , g.TotalPoints__c , g.ValidUntil__c, g.date_1
,h.TotalPoints__c , h.ValidUntil__c, h.date_2

Resulting nulls on full join not being replaced

I have a set of select queries using full join (required) and would like to replace the resulting nulls with something else (in the following example, it should be "empty").
For the first column (and all others, honestly) I have tried using isnull(), coallesce(), case when and even try_convert, but the result is always null. I'm ok with null, as in this particular case means that the results from the first query don't exist the second query, which is my goal.
There are following, identical queries, also full join 'd, so a line in the first query may not be in the second query but may be in the third of fourth queries.
Here is the select statement
SELECT *
FROM (SELECT Isnull(1, 'empty') AS SubGroup
, table2.lineintid AS OrderByThis2nd
, table2.HeaderStamp AS HeaderLink
, table2.linestamp AS LineID
, table2.lprocessname AS LineProcName
, table2.lprocessno AS LineProcNumber
, table2.productid AS ProdId
, table2.prodamount AS QTT
, table2.prodval AS UnitPrice
FROM table2 (nolock)
INNER JOIN table1 ON table2.headerstamp = table1.headerstamp
WHERE table1.lprocessname = 'Phase 1')Proc1L
FULL JOIN (SELECT Isnull(2, 'empty') AS SubGroup
, table2.lineintid AS OrderByThis2nd
, table2.linestamp AS LineID
, table2.prevlstamp AS PrecedingLine
, table2.lprocessname AS LineProcName
, table2.lprocessno AS LineProcNumber
, table2.productid AS ProdId
, table2.prodamount AS QTT
, table2.prodval AS UnitPrice
FROM table2 (nolock)
INNER JOIN table1 ON table2.headerstamp = table1.headerstamp
WHERE table1.lprocessname = 'Phase 2'
AND Year(table2.linedate) = '2018')Proc2L ON Proc1L.LineID = Proc2L.PrecedingLine
ORDER BY 1 DESC
, 2
This database is in MS SQL 2014.
Any ideas are appreciated. Thank you very much!
Try using ISNULL function in the outer query. Instead of
select * from
use
Select isnull(col1, 'x'), etc
from

How to use Left join instead of inner join

I have written the following query, that joins a table with already joined tables. I have basically used inner join using SQL Server. I am wondering how to modify the below code to use Left join rather than inner join?
The below query has three tables Blended, BOUND_TAB and RECORD
The second thing is, I also need to filter the results such that I use policies with deductibleinUSD > 0 in 'Blended' table or Primary_R Type = 'Deductible' and Primary_R Amount > 0 from the inner select. This should provide me the policies in my final results if either 'Blended' or 'BOUND_TAB' indicates that it has a deductible.
select
c.MPolicyNumber,
c.SNumber,
c.InsuredName,
c.EffDate,
c.Renewal,
c.GPremiumUSD,
c.Status,
c.deductibleinUSD, t.*
from
IT.dbo.Blended c
inner join
(select distinct
a.[Policy Number], a.[LOB],
a.[Primary_R Amount] as Bound_deductibles,
a.[Primary_R Type],
a.[EffDate] as CAS_EffDate
from
IT.dbo.BOUND_TAB a
inner join
IT.dbo.RECORD b on a.idxFile = b.[Bound Rater]
where
a.[Primary Retention Amount] > 0) t on t.[Policy Number] = c.MPolicyNumber
where
c.deductibleinUSD > 0
and c.ProductLine in ('Health','Cas')
order by
c.EffDate
Thanks in advance !
Without example data and an example of desired results, this is the best I can guess based on your question:
select
c.MPolicyNumber
, c.SNumber
, c.InsuredName
, c.EffDate
, c.Renewal
, c.GPremiumUSD
, c.Status
, c.deductibleinUSD
, t.*
from IT.dbo.Blended c
left join (
select distinct
a.[Policy Number]
, a.[LOB]
, a.[Primary_R Amount] as Bound_deductibles
, a.[Primary_R Type]
, a.[EffDate] as CAS_EffDate
from IT.dbo.BOUND_TAB a
inner join IT.dbo.RECORD b
on a.idxFile = b.[Bound Rater]
where a.[Primary Retention Amount] > 0
) as t
on t.[Policy Number] = c.MPolicyNumber
and c.ProductLine in ('Health','Cas')
and (c.deductibleinUSD > 0
or (Primary_R Type = 'Deductible'
and Bound_deductibles > 0
)
)
order by c.EffDate

Update records SQL?

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

Group by - multiple conditions - MySQL

How can I combine 2 group by conditions? I have records for each id for every hour in a day and I want to group information by first id and all records for that id in that day then second id and all records for that in the day.
My sample query is this:
SELECT
r.name
, r.network
, r.namestring
, i.name
, i.description
, r.rid
, i.id
, d.dtime
, d.ifInOctets
FROM router AS r
INNER JOIN interface AS i
ON r.rid = i.rid
INNER JOIN 1279080000_1_60 AS d
ON i.id = d.id
AND dtime BETWEEN 1279113600 AND 1279115400
WHERE r.network = "ITPN"
AND i.status = "active"
GROUP BY i.id AND d.dtime // each id with all its dtime
This always ends up giving me an aggregate value for that id.
Any idea what I could use??? I don't want to sum up all values.
Thank you,
To group by multiple expressions you should separate them with a comma, not AND:
GROUP BY i.id, d.dtime
You should also ensure that two records form the same day have the same value of dtime. It's not clear from your question whether this is or is not the case.

Resources