COALESCE vs OR condition for JOIN (SQL) - sql

I have Event table
TABLE Event(
EventId [int] IDENTITY(1,1) NOT NULL,
EventSource1Id [int] NULL,
EventSource2Id [int] NULL
)
that contains info about events from different sources
where one of the event sources can be null
TABLE EventSource1(
Id [int] IDENTITY(1,1) NOT NULL,
Name [nvarchar](50) NULL,
VenueId [int] NOT NULL
)
and
TABLE EventSource2(
Id [int] IDENTITY(1,1) NOT NULL,
Name [nvarchar](50) NULL,
VenueId [int] NOT NULL
)
TABLE Venue(
Id [int] IDENTITY(1,1) NOT NULL,
TimeZone [nvarchar](100) NOT NULL
)
I'd like to create view, but I'm not sure what is the best way to use: coalesce vs OR condition for JOIN
First option:
SELECT
ev.[Id] AS 'Id',
ven.[Id] AS 'VenueId'
FROM Event ev
LEFT JOIN EventSource1 source1 ON source1.[Id] = ev.EventSource1Id
LEFT JOIN EventSource2 source1 ON source2.[Id] = ev.EventSource2Id
LEFT JOIN Venue AS ven ON ven.[Id] = source1.[VenueId] OR v.[Id] = source2.[VenueId]
Second option:
SELECT
ev.[Id] AS 'Id',
ven.[Id] AS 'VenueId'
FROM Event ev
LEFT JOIN EventSource1 source1 ON source1.[Id] = ev.EventSource1Id
LEFT JOIN EventSource2 source1 ON source2.[Id] = ev.EventSource2Id
LEFT JOIN Venue AS ven ON ven.[Id] = COALESCE(source1.[Id], source2.[Id])
Could you help me please?

The COALESCE will typically yield a better query plan. You should test with your data.

Related

SQL Server: select records, not linked to another table

I have a table:
CREATE TABLE [dbo].[CollectionSite]
(
[SiteCode] [nvarchar](32) NOT NULL,
[AddressId] [int] NOT NULL,
[RemittanceId] [int] NULL,
// additional columns
)
and a linked table:
CREATE TABLE [dbo].[CollectionSiteAddress]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](255) NULL,
[Address1] [nvarchar](255) NULL,
[Address2] [nvarchar](255) NULL,
[City] [nvarchar](128) NULL,
[State] [nvarchar](64) NULL,
[Zip] [nvarchar](32) NULL,
)
Relationship between these 2 tables:
ALTER TABLE [dbo].[CollectionSite] WITH CHECK
ADD CONSTRAINT [FK_CollectionSite_CollectionSiteAddress_AddressId]
FOREIGN KEY([AddressId]) REFERENCES [dbo].[CollectionSiteAddress] ([Id])
GO
ALTER TABLE [dbo].[CollectionSite] WITH CHECK
ADD CONSTRAINT [FK_CollectionSite_CollectionSiteAddress_RemittanceId]
FOREIGN KEY([RemittanceId]) REFERENCES [dbo].[CollectionSiteAddress] ([Id])
GO
I want to select all records from CollectionSiteAddress, which are not linked to CollectionSite (neither AddressId nor RemittanceId). Which request should I use?
I tried:
SELECT *
FROM CollectionSiteAddress
LEFT JOIN CollectionSite ON CollectionSiteAddress.Id = CollectionSite.AddressId
OR CollectionSiteAddress.Id = CollectionSite.RemittanceId
but it selects all records from CollectionSiteAddress
You are missing this WHERE clause:
WHERE CollectionSite.[SiteCode] IS NULL
because you want all the unmatched rows of CollectionSiteAddress.
I used the column [SiteCode] to check if it is NULL because it is not nullable in the definition of the table.
So you can write your query like this (shortened with aliases):
SELECT csa.*
FROM CollectionSiteAddress csa LEFT JOIN CollectionSite cs
ON csa.Id = cs.AddressId OR csa.Id = cs.RemittanceId
WHERE cs.[SiteCode] IS NULL
Or use NOT EXISTS:
SELECT csa.*
FROM CollectionSiteAddress csa
WHERE NOT EXISTS (
SELECT 1
FROM CollectionSite cs
WHERE csa.Id = cs.AddressId OR csa.Id = cs.RemittanceId
)

Query Failed to Join two tables records into gridview

I am trying to join two tables by using SQL query by using single parameters. I have two tables student and student job record and I want to join this two table into single a single based on ID.
Student profile table.
CREATE TABLE [dbo].[Student_Profile]
(
[StudentID] [int] IDENTITY(1,1) NOT NULL,
[First_Name] [varchar](50) NULL,
[Last_Name] [varchar](50) NULL,
[Email] [varchar](500) NULL,
[Qualifactions] [varchar](50) NULL,
[Name_Of_Instatutions] [varchar](50) NULL,
[City] [varchar](50) NULL,
[Country] [varchar](50) NULL,
[Contract] [varchar](50) NULL
) ON [PRIMARY]
Here is the student job profile table.
CREATE TABLE [dbo].[Student_Job_Record]
(
[Record_ID] [int] IDENTITY(1,1) NOT NULL,
[StudentID] [int] NULL,
[Total_Hours_Work] [varchar](50) NULL,
[Pay_Rate] [varchar](50) NULL,
[Total_Amount_Paid] [varchar](500) NULL
) ON [PRIMARY]
I am using a stored procedure to display the data into gridview. Here is the stored procedure code.
CREATE PROCEDURE [dbo].[spGetStudentsDeatilsByID]
#ID int
AS
BEGIN
SELECT
Student_Profile.First_Name, Student_Profile.Last_Name,
Job_Profile.Title, Job_Profile.Location,
Job_Profile.Type_Contract, Job_Profile.Salary
FROM
Student_Profile, Job_Profile
WHERE
Student_Profile.StudentID = #ID
AND Job_Profile.StudentID = #ID
END
I want to display and join this two table into gridview based on studentID. But when I enter the student Id and click the submit button, nothing is displayed.
Here is the screen shot when I run the applications.
Try the following. If you do not have StudentID in Job_Profile then you can use LEFT JOIN.
Create proc [dbo].[spGetStudentsDeatilsByID]
#ID int
as
Begin
SELECT
sp.First_Name,
sp.Last_Name ,
jp.Title,
jp.Location,
jp.Type_Contract,
jp.Salary
FROM Student_Profile sp
LEFT JOIN Job_Profile jp
ON sp.StudentID = jp.StudentID
WHERE sp.StudentID =#ID
End
GO

SQL Query to update a colums from a table base on a datetime field

I have 2 table called tblSetting and tblPaquets.
I need to update 3 fields of tblPaquets from tblSetting base on a where clause that use a datetime field of tblPaquest and tblSetting.
The sql below is to represent what I am trying to do and I know it make no sense right now.
My Goal is to have One query to achieve this goal.
I need to extract the data from tblSettings like this
SELECT TOP(1) [SupplierID],[MillID],[GradeFamilyID] FROM [tblSettings]
WHERE [DateHeure] <= [tblPaquets].[DateHeure]
ORDER BY [DateHeure] DESC
And Update tblPaquets with this data
UPDATE [tblPaquets]
SET( [SupplierID] = PREVIOUS_SELECT.[SupplierID]
[MillID] = PREVIOUS_SELECT.[MillID]
[GradeFamilly] = PREVIOUS_SELECT.[GradeFamilyID] )
Here the table design
CREATE TABLE [tblSettings](
[ID] [int] NOT NULL,
[SupplierID] [int] NOT NULL,
[MillID] [int] NOT NULL,
[GradeID] [int] NOT NULL,
[TypeID] [int] NOT NULL,
[GradeFamilyID] [int] NOT NULL,
[DateHeure] [datetime] NOT NULL,
[PeakWetEnable] [tinyint] NULL)
CREATE TABLE [tblPaquets](
[ID] [int] IDENTITY(1,1) NOT NULL,
[PaquetID] [int] NOT NULL,
[DateHeure] [datetime] NULL,
[BarreCode] [int] NULL,
[Grade] [tinyint] NULL,
[SupplierID] [int] NULL,
[MillID] [int] NULL,
[AutologSort] [tinyint] NULL,
[GradeFamilly] [int] NULL)
You can do this using CROSS APPLY:
UPDATE p
SET SupplierID = s.SupplierID,
MillID = s.MillID
GradeFamilly = s.GradeFamilyID
FROM tblPaquets p CROSS APPLY
(SELECT TOP (1) s.*
FROM tblSettings s
WHERE s.DateHeure <= p.DateHeure
ORDER BY p.DateHeure DESC
) s;
Notes:
There are no parentheses before SET.
I don't recommend using [ and ] to escape identifiers, unless they need to be escaped.
I presume the query on tblSettings should have an ORDER BY to get the most recent rows.

How do I aggregate 3 columns that are different with MIN(DATE)?

I'm facing a simple problem here that I can't solve, I have this query:
SELECT
MIN(TEA_InicioTarefa),
PFJ_Id_Analista,
ATC_Id,
SRV_Id
FROM
dbo.TarefaEtapaAreaTecnica
INNER JOIN Tarefa t ON t.TRF_Id = TarefaEtapaAreaTecnica.TRF_Id
WHERE SRV_Id = 88
GROUP BY SRV_Id, ATC_Id, PFJ_Id_Analista
ORDER BY ATC_Id ASC
It returns me this:
I was able to group it a little with GROUP BY SRV_Id, ATC_Id, PFJ_Id_Analista that gave me these 8 records, but as you can see some PFJ_Id_Analista are different.
What I want is to select only the early date of each SRV_Id and ATC_Id, the PFJ_Id_Analista don't need to grup, if I remove PFJ_Id_Analista from the grouping the query works, but I need the column.
For eg.: between row number 2 and 3 I want only the early date, so it will be row 2. The same goes for rows 5 to 8, I want only row 6.
DDL for TarefaEtapaAreaTecnica (important key: TRF_Id)
CREATE TABLE [dbo].[TarefaEtapaAreaTecnica](
[TEA_Id] [int] IDENTITY(1,1) NOT NULL,
**[TRF_Id] [int] NOT NULL,**
[ETS_Id] [int] NOT NULL,
[ATC_Id] [int] NOT NULL,
[TEA_Revisao] [int] NOT NULL,
[PFJ_Id_Projetista] [int] NULL,
[TEA_DoctosQtd] [int] NULL,
[TEA_InicioTarefa] [datetime2](7) NULL,
[PFJ_Id_Analista] [int] NULL,
[TEA_FimTarefa] [datetime2](7) NULL,
[TEA_HorasQtd] [numeric](18, 1) NULL,
[TEA_NcfQtd] [int] NULL,
[PAT_Id] [int] NULL
DDL for Tarefa (important keys TRF_Id and SRV_Id (which I need it)):
CREATE TABLE [dbo].[Tarefa](
**[TRF_Id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,**
**[SRV_Id] [int] NOT NULL,**
[TRT_Id] [int] NOT NULL,
[TRF_Descr] [varchar](255) NULL,
[TRF_Entrada] [datetime] NOT NULL,
[TRF_DoctosQtd] [int] NOT NULL,
[TRF_Devolucao] [datetime] NULL,
[TRF_NcfQtd] [int] NULL,
[TRF_EhDocInsuf] [bit] NULL,
[TRF_Observ] [varchar](255) NULL,
[TRF_AreasTrfQtd] [int] NULL,
[TRF_AreasTrfLiqQtd] [int] NULL
Thanks a lot.
EDIT:
CORRECT QUERY
Based on #Gordon Linoff post:
select t.TEA_InicioTarefa, t.PFJ_Id_Analista, t.ATC_Id, t.SRV_Id
from (select t.*,
row_number() over (partition by ATC_Id, SRV_Id
order by TEA_InicioTarefa) as seqnum, ta.SRV_Id
from dbo.TarefaEtapaAreaTecnica t
inner join dbo.Tarefa ta on t.TRF_Id = ta.TRF_Id
) t
where seqnum = 1 AND t.SRV_Id = 88
Just use window functions:
select t.*
from (select t.*,
row_number() over (partition by ATC_Id, SRV_Id
order by ini) as seqnum
from dbo.TarefaEtapaAreaTecnica t
) t
where seqnum = 1;
This is really an example of filtering, not aggregation. The problem is getting the right value to filter on.
Then get the grouping first and then do a JOIN with it like
SELECT
x.Min_TEA_InicioTarefa,
t.PFJ_Id_Analista,
t.ATC_Id,
t.SRV_Id
FROM
dbo.TarefaEtapaAreaTecnica t
INNER JOIN Tarefa ta ON ta.TRF_Id = t.TRF_Id
INNER JOIN (
select SRV_Id, MIN(TEA_InicioTarefa) as Min_TEA_InicioTarefa
from dbo.TarefaEtapaAreaTecnica
GROUP BY SRV_Id
) x ON t.SRV_Id = x.SRV_Id
WHERE t.SRV_Id = 88
ORDER BY t.ATC_Id ASC;

Joining SQL tables

I have a customer table that has primary information about the customer like, name, lastname,password,… I have a Address, Email, Phone table that has for example 3 kinds of address , 2 phone number, 2 email address for each customer. I have a Type table that TypeID and Type_Group,Type_Value. For example:
TypeID Type_Group Type_Value
1 Address Work
2 Address Home
3 Address mailing
4 Email Primary
5 Email secondary
I know how to join customer table with address, Email and phone table. I don't know how to join the Address, phone,Email with type Table.
This is my Query:
SELECT
cc.[Customer_ID]
,[Account_Number]
,[First_Name]
,[Middle_Name]
,[Last_Name]
,[Password]
,ce.[Email]
,cph.Phone_Number
,ca.Address_1
,ca.Address_2
,ca.City
,ca.State
,ca.Zip
,tp.Type_Desc
FROM [CustomerPortal].[dbo].[Customer] cc WITH (NOLOCK)
left join [CustomerPortal].[dbo].Customer_Email ce WITH (NOLOCK) on cc.Customer_ID = ce.Customer_ID
left join [CustomerPortal].[dbo].Customer_Address ca WITH (NOLOCK) on cc.Customer_ID =cp.Customer_ID
left join [CustomerPortal].[dbo].Customer_Phone cph WITH (NOLOCK) on cc.Customer_ID =cph.Customer_ID
WHERE cc.Customer_ID=#Customer_ID
This is Tables:
this is customer Table:
(PRIMARY KEY)[Customer_ID] [int] IDENTITY(1,1) NOT NULL,
[Account_Number] [int] NULL,
[First_Name] [varchar](50) NULL,
[Middle_Name] [varchar](50) NULL,
Customer Address Table:
[dbo].[Customer_Address](
primary key[Customer_Address_ID] [int] IDENTITY(1,1) NOT NULL,
Fkey [Customer_ID] [int] NOT NULL,
[Address_1] [varchar](100) NULL,
[Address_2] [varchar](100) NULL,
[City] [varchar](100) NULL,
[State] [varchar](10) NULL,
[Zip] [varchar](10) NULL,
Fkey [Address_Type] [int] NULL,
CustomerEmail Table:
[dbo].[Customer_Email](
PKey [Customer_Email_ID] [int] IDENTITY(1,1) NOT NULL,
Fkey [Customer_ID] [int] NOT NULL,
[Email] [varchar](50) NULL,
Fkey [Email_Type] [int] NULL,
Customer Phone Table:
PK [dbo].[Customer_Phone](
FK [Customer_Phone_ID] [int] IDENTITY(1,1) NOT NULL,
[Customer_ID] [int] NOT NULL,
[Phone_Number] [bigint] NULL,
FK [Phone_Type] [int] NULL,
Type Table:
PK [dbo].[Type_XREF](
[Type_ID] [int] IDENTITY(1,1) NOT NULL,
[Type_Group] [varchar](25) NULL,
[Type_Value] [varchar](50) NULL,
[Type_Desc] [varchar](100) NULL,
I am not sure how to add join to Type Table, any thing I try produce me several Rows, as I want to have 1 row for customer with name, All related Home address,All related mailing address, primary email,secondary email,.... So all customer info in 1 line of record.
You can join each of the tables to the type table seperately, since their Type ID will correspond to one of the IDs in the type table. Even though the types are mixed in the table, each element in their respective table would reasonable have a logical type assigned to it. I'll just make an assumption on the format that you want to display the Type in and the name of the table:
SELECT
cc.[Customer_ID]
,[Account_Number]
,[First_Name]
,[Middle_Name]
,[Last_Name]
,[Password]
,ce.[Email]
,cph.Phone_Number
,ca.Address_1
,ca.Address_2
,ca.City
,ca.State
,ca.Zip
,tp.Type_Desc
,te.Type_Group + '-' + te.Type_Value as [EmailType]
,ta.Type_Group + '-' + ta.Type_Value as [AddressType]
,tph.Type_Group + '-' + tph.Type_Value as [PhoneType]
FROM [CustomerPortal].[dbo].[Customer] cc WITH (NOLOCK)
left join [CustomerPortal].[dbo].Customer_Email ce WITH (NOLOCK) on cc.Customer_ID = ce.Customer_ID
left join [CustomerPortal].[dbo].Customer_Address ca WITH (NOLOCK) on cc.Customer_ID =cp.Customer_ID
left join [CustomerPortal].[dbo].Customer_Phone cph WITH (NOLOCK) on cc.Customer_ID =cph.Customer_ID
left join [dbo].Type_Table te on te.ID = ce.Type
left join [dbo].Type_Table ta on ta.ID = ca.Type
left join [dbo].Type_Table tph on tph.ID = cph.Type