SQL query that can display data with a null ID and with not null id on the same Datatable? - sql

Hello I have a question here...
I'll show you my tables first...
[Vendedores](
[IdVendedor] [int] IDENTITY(1,1) NOT NULL,
[IdGrupo] [int] NULL,
[IdInfoContacto] [int] NULL,
[ApellidoPaterno] [varchar](30) NULL,
[ApellidoMaterno] [varchar](30) NULL,
[Nombre] [varchar](35) NULL,
[Estado] [varchar](10) NULL,
CONSTRAINT [PK_Vendedores] PRIMARY KEY CLUSTERED
[Clientes](
[IdCliente] [int] IDENTITY(1,1) NOT NULL,
[IdGrupo] [int] NULL,
[IdVendedor] [int] NULL,
[IdDireccion] [int] NULL,
[IdInfoContacto] [int] NULL,
[FechaAlta] [date] NULL,
[ApellidoPaterno] [varchar](30) NULL,
[ApellidoMaterno] [varchar](30) NULL,
[Nombre] [varchar](40) NULL,
[Empresa] [text] NULL,
[Estado] [varchar](20) NULL,
[Estatus] [varchar](20) NULL,
CONSTRAINT [PK_Clientes] PRIMARY KEY CLUSTERED
[dbo].[Mensajes](
[IdMensaje] [int] IDENTITY(1,1) NOT NULL,
[IdCliente] [int] NULL,
[IdVendedor] [int] NULL,
[CorreoRemitente] [varchar](100) NULL,
[CorreoCliente] [varchar](100) NULL,
[CorreosAdicionales] [varchar](max) NULL,
[Tema] [varchar](100) NULL,
[Mensaje] [varchar](max) NULL,
[Fecha] [date] NULL,
[Hora] [time](5) NULL,
CONSTRAINT [PK_Mensajes] PRIMARY KEY CLUSTERED
[Archivos](
[IdArchivo] [int] IDENTITY(1,1) NOT NULL,
[IdMensaje] [int] NULL,
[Nombre] [varchar](max) NULL,
[Ubicacion] [varchar](50) NULL,
CONSTRAINT [PK_Archivos] PRIMARY KEY CLUSTERED
There are 2 ways to send messages in the system I'm developing...:
the first one is, you select a client, and when the message is sent, the client's ID (IdCliente) is taken from Clientes Table and inserted in a new row in Mensajes table.
that way, when you want to check all of the sent messages, you can clearly see to which client was sent.
the second one would be a free one, you send to whoever you want, you don't have to select a client. Therefore, when you register the new message, the IdCliente column would be null.
Some notes out of the way now: Vendedor is the seller or user who sent the message, Archivos means files, and in case you want to attach files, for each one of them, a new row in Archivos would be inserted and each with the same IdMensaje.
FOR THE moment, I have a query that allows me to see all my messages (with clients), and to also show how many files were attached to that message. HERE IT IS:
SELECT (Clientes.ApellidoPaterno + ' ' + Clientes.ApellidoMaterno + ' ' + Clientes.Nombre) AS Cliente, Mensajes.* FROM (SELECT Mensajes.IdMensaje, Mensajes.IdCliente, Mensajes.IdVendedor, Mensajes.CorreoRemitente, Mensajes.CorreoCliente, Mensajes.CorreosAdicionales, Mensajes.Tema, Mensajes.Mensaje, Mensajes.Fecha, Mensajes.Hora, COUNT(Archivos.IdArchivo) AS Archivos FROM Mensajes LEFT OUTER JOIN Archivos ON Mensajes.IdMensaje = Archivos.IdMensaje GROUP BY Mensajes.IdMensaje, Mensajes.IdCliente, Mensajes.IdVendedor, Mensajes.CorreoRemitente, Mensajes.CorreoCliente, Mensajes.CorreosAdicionales, Mensajes.Tema, Mensajes.Mensaje, Mensajes.Fecha, Mensajes.Hora) AS Mensajes JOIN Clientes ON Clientes.IdCliente = Mensajes.IdCliente ORDER BY Mensajes.Fecha DESC, Mensajes.Hora DESC
"(Clientes.ApellidoPaterno + ' ' + Clientes.ApellidoMaterno + ' ' + Clientes.Nombre) AS Cliente" Displays the full name of the client
however, now I want to have a query in which displays the same information as above... plus the following...
Messages with IdCliente = null
if IdCliente = null then the Cliente Column that I mentioned above would be "" (blank space)
If I need to be more specific, please let me know in what part must I give more information.
I hope you guys can help me
Thanks in advance

Firstly, change your JOIN to a LEFT JOIN:
LEFT JOIN Clientes ON Clientes.IdCliente = Mensajes.IdCliente
This will allow Messages with no associated IdCliente to remain. To get the desired blank space, use COALESCE:
COALESCE(Clientes.ApellidoPaterno + ' ' + Clientes.ApellidoMaterno + ' ' + Clientes.Nombre, '') AS Cliente

Related

t-sql end of month insert

I have created two database tables named TSALESFACT and DimDate. TSALESFACT table contains the monthly sales target values. And DimTime contains the date values which begins from 01/01/2005.
CREATE TABLE [dbo].[TSalesFact](
[DateID] [smalldatetime] NULL,
[YearID] [int] NOT NULL,
[MonthID] [int] NOT NULL,
[SeasonID] [char](10) NOT NULL,
[DepartmentID] [char](10) NOT NULL,
[SalesAmount] [int] NOT NULL
)
CREATE TABLE [dbo].[dim_Date](
[ID] [int] NOT NULL,
[Date] [datetime] NOT NULL,
[Day] [char](2) NOT NULL,
[DaySuffix] [varchar](4) NOT NULL,
[DayOfWeek] [varchar](9) NOT NULL,
[DOWInMonth] [tinyint] NOT NULL,
[DayOfYear] [int] NOT NULL,
[WeekOfYear] [tinyint] NOT NULL,
[WeekOfMonth] [tinyint] NOT NULL,
[Month] [char](2) NOT NULL,
[MonthName] [varchar](9) NOT NULL,
[Quarter] [tinyint] NOT NULL,
[QuarterName] [varchar](6) NOT NULL,
[Year] [char](4) NOT NULL,
[StandardDate] [varchar](10) NULL,
[HolidayText] [varchar](50) NULL)
I would like to INSERT these sales target values into a new table named DailySalesTargets. But, the main purpose of this operation is writing the target sales to the each of end of month date. All of the date values for the relevant month will be zero. My desired resultset for this operation is like below:
How can I achieve this? Any idea?
I think this is what you are trying to do.
insert into [DailySalesTargets]([DateID],[YearID],[MonthID],
[SeasonID],[DepartmentID],[SalesAmount])
select d.[Date],d.[Year],d.[Month]
,dptSeason.[SeasonID],dptSeason.[DepartmentID]
,case when EOMONTH(d.[Date])=s.[DateID] then s.[SalesAmount] else 0 end as [SalesAmount]
from [dbo].[dim_Date] d
cross join (select distinct [DepartmentID],[SeasonID] from [dbo].[TSalesFact]) dptSeason
left join [dbo].[TSalesFact] s on d.[Date] = s.[DateID]
and s.[DepartmentID]=dptSeason.[DepartmentID]
and s.[SeasonID]=dptSeason.[SeasonID]

SQL Server partition and index

I have a requirement to design a table that is going to have around 80 million records. I created a partition for every month using persisted column (if its wrong suggest me the best way). Please find below scripts that I used to create tables and partition and the query that's going to be used often. Only Insertion and deletion will be done on this table.
-- Create the Partition Function
CREATE PARTITION FUNCTION PF_Invoice_item (int)
AS RANGE LEFT FOR VALUES (1,2,3,4,5,6,7,8,9,10,11,12);
-- Create the Partition Scheme
CREATE PARTITION SCHEME PS_Invoice_item
AS PARTITION PF_Invoice_item ALL TO ([Primary]);
CREATE TABLE [Invoice]
(
[invoice_id] [bigint] NOT NULL,
[Invoice_Number] [varchar](255) NULL,
[Invoice_Date] [date] NULL,
[Invoice_Total] [numeric](18, 2) NULL,
[Outstanding_Balance] [decimal](18, 2) NULL,
CONSTRAINT [PK_Invoice_id] PRIMARY KEY CLUSTERED([invoice_id] ASC)
)
CREATE TABLE [InvoiceItem](
[invoice_item_id] [bigint] NOT NULL,
[invoice_id] [bigint] NOT NULL,
[invoice_Date] [date] NULL,
[make] [varchar](255) NULL,
[serial_number] [varchar](255) NULL,
[asset_id] [varchar](100) NULL,
[application] [varchar](255) NULL,
[customer] [varchar](255) NULL,
[ucid] [varchar](255) NULL,
[dcn] [varchar](255) NULL,
[dcn_name] [varchar](255) NULL,
[device_serial_number] [varchar](255) NULL,
[subscription_name] [varchar](255) NULL,
[product_name] [varchar](255) NULL,
[subscription_start_date] [date] NULL,
[subscription_end_date] [date] NULL,
[duration] [varchar](50) NULL,
[promo_name] [varchar](255) NULL,
[promo_end_date] [date] NULL,
[discount] [decimal](18, 2) NULL,
[tax] [decimal](18, 2) NULL,
[line_item_total] [decimal](18, 2) NULL,
[mth] AS (datepart(month,[invoice_date])) PERSISTED NOT NULL,**
[RELATED_PRODUCT_RATEPLAN_NAME] [varchar](250) NULL,
[SUB_TOTAL] [decimal](18, 2) NULL,
[BILLING_START_DATE] [date] NULL,`enter code here`
[BILLING_END_DATE] [date] NULL,
[SUBSCRIPTION_ID] [varchar](200) NULL,
[DEVICE_TYPE] [varchar](200) NULL,
[BASE_OR_PROMO] [varchar](200) NULL,
CONSTRAINT [PK_InvoiceItem_ID] PRIMARY KEY CLUSTERED ([invoice_item_id]
ASC,[mth] ASC))
ON PS_Invoice_item(mth);
GO
ALTER TABLE [InvoiceItem] WITH CHECK ADD CONSTRAINT [FK_Invoice_ID]
FOREIGN KEY([invoice_id])
REFERENCES [Invoice] ([invoice_id])
GO
I will be using below queries
select subscription_name,duration,start_date,end_date,promotion_name,
promotion_end_date,sub_total,discount,tax,line_item_total from InvoiceItem
lt inner join Invoice on lt.invoice_id=invoice.invoice_id where
invoice.invoice_number='' and lt.customer='' and lt.ucid='' lt.make='' and
lt.SERIAL_NUMBER='' and lt.dcn='' and lt.application=''
select customer,make,application from billing.AssetApplicationTotals
lineItem inner join billing.Invoice invoice on
lineItem.invoice_id=invoice.invoice_id where invoice.invoice_number='';
SELECT [invoice_Date],[make],[serial_number],[application],[customer],
[ucid],[dcn],[dcn_name],[device_serial_number]
,[subscription_name],[product_name],[subscription_start_date],
[subscription_end_date],[duration],[promo_name],[promo_end_date]
FROM [InvoiceItem] where [application]=''
SELECT [invoice_Date],[make],[serial_number],[application],[customer],
[ucid],[dcn],[dcn_name],[device_serial_number]
,[subscription_name],[product_name],[subscription_start_date],
[subscription_end_date],[duration],[promo_name],[promo_end_date]
FROM [InvoiceItem] where [customer]=''
What is the best way to create index? Shall I create separate non clustered index for each filter, or shall I have Composite index and shall I have covering index to avoid key lookup?

SQL Query - Complex query between tables

I currently have the 5 following tables. Each Site has (1 or Many) Project Managers as well as (1 or Many) Site_Supervisors. A Project Manager / Site Supervisor can be assigned to many sites
I currently have a working query:
SELECT Sites.Site_Name, Sites.Site_Street_Address, Sites.Site_Suburb, Sites.Site_State, Sites.Site_Postcode, Sites.Site_Region, Sites.Completed, Project_Managers.First_Name AS PM_First_Name, Project_Managers.Last_Name AS PM_Last_Name, Site_Supervisors.First_Name AS SS_First_Name, Site_Supervisors.Last_Name AS SS_Last_Name, Sites.Date_Started
FROM Site_Site_Supervisors INNER JOIN
Site_Supervisors ON Site_Site_Supervisors.Site_Supervisor_ID = Site_Supervisors.Site_Supervisor_ID RIGHT OUTER JOIN
Sites ON Site_Site_Supervisors.Site_ID = Sites.Site_ID LEFT OUTER JOIN
Project_Managers INNER JOIN
Site_Project_Managers ON Project_Managers.Project_Manager_ID = Site_Project_Managers.Project_Manager_ID ON
Sites.Site_ID = Site_Project_Managers.Site_ID
WHERE (Sites.Completed = 0)
ORDER BY Sites.Site_Name
Which gives me the desired output, which i then work with in my code.
I am wanting to make a change to the query, where instead of outputting the:
Project_Managers.First_Name AS PM_First_Name
Project_Managers.Last_Name AS PM_Last_Name
instead i replace these with:
Project_Managers.First_Name where the corresponding Site_Project_Managers.Primary_Contact = True AS PM_First_Name
Project_Managers.Last_Name where the corresponding Site_Project_Managers.Primary_Contact = True AS PM_Last_Name
Project_Managers.First_Name where the corresponding Site_Project_Managers.Primary_Contact = False AS AssistantPM_First_Name
Project_Managers.Last_Name where the corresponding Site_Project_Managers.Primary_Contact = False AS AssistantPM_Last_Name
To perform this query is beyond my SQL skillset at this time, so i am hoping one of you can provide me with the correct query to use and or some guidance
Thanks
Sites
[Site_ID] [int] IDENTITY(1,1) NOT NULL (PK),
[Site_Name] [varchar](50) NOT NULL,
[Site_Street_Address] [varchar](50) NULL,
[Site_Suburb] [varchar](50) NULL,
[Site_State] [varchar](50) NULL,
[Site_Postcode] [varchar](10) NULL,
[Site_Region] [varchar](50) NULL,
[Date_Started] [datetime] NULL,
[Completed] [bit] NOT NULL
Project_Managers
[Project_Manager_ID] [int] IDENTITY(1,1) NOT NULL (PK),
[First_Name] [varchar](50) NOT NULL,
[Last_Name] [varchar](50) NOT NULL,
[Phone_Number] [varchar](50) NULL,
[Email_Address] [varchar](50) NULL,
[Currently_Employed] [bit] NOT NULL,
CONSTRAINT [PK_Project_Managers] PRIMARY KEY CLUSTERED
Site_Supervisors
[Site_Supervisor_ID] [int] IDENTITY(1,1) NOT NULL (PK),
[First_Name] [varchar](50) NOT NULL,
[Last_Name] [varchar](50) NOT NULL,
[Phone_Number] [varchar](50) NULL,
[Email_Address] [varchar](50) NULL,
[Currently_Employed] [bit] NOT NULL,
CONSTRAINT [PK_Site_Supervisors_1] PRIMARY KEY CLUSTERED
Site_Project_Managers
[Site_ID] [int] NOT NULL (PK),
[Project_Manager_ID] [int] NOT NULL (PK),
[Primary_Contact] [bit] NULL,
[Alerts] [bit] NULL,
CONSTRAINT [PK_Site_Project_Managers] PRIMARY KEY CLUSTERED
Site_Site_Supervisors
[Site_ID] [int] NOT NULL (PK),
[Site_Supervisor_ID] [int] NOT NULL (PK),
[Primary_Contact] [bit] NULL,
[Alerts] [bit] NULL,
CONSTRAINT [PK_Site_Site_Supervisors] PRIMARY KEY CLUSTERED
Assumed you are using MySql and you may use the CASE or inline IF ELSE to get the desired output that you want
SELECT Sites.Site_Name,
Sites.Site_Street_Address,
Sites.Site_Suburb,
Sites.Site_State,
Sites.Site_Postcode,
Sites.Site_Region,
Sites.Completed,
CASE Site_Project_Managers.Primary_Contact
WHEN true THEN Project_Managers.First_Name
END AS PM_First_Name,
CASE Site_Project_Managers.Primary_Contact
WHEN true THEN Project_Managers.Last_Name
END AS PM_Last_Name,
CASE Site_Project_Managers.Primary_Contact
WHEN false THEN Project_Managers.First_Name
END AS AssistantPM_First_Name,
CASE Site_Project_Managers.Primary_Contact
WHEN false THEN Project_Managers.Last_Name
END AS AssistantPM_Last_Name,
Site_Supervisors.First_Name AS SS_First_Name,
Site_Supervisors.Last_Name AS SS_Last_Name,
Sites.Date_Started
FROM Site_Site_Supervisors
INNER JOIN Site_Supervisors
ON Site_Site_Supervisors.Site_Supervisor_ID = Site_Supervisors.Site_Supervisor_ID
RIGHT OUTER JOIN Sites
ON Site_Site_Supervisors.Site_ID = Sites.Site_ID
LEFT OUTER JOIN Project_Managers
INNER JOIN Site_Project_Managers
ON Project_Managers.Project_Manager_ID = Site_Project_Managers.Project_Manager_ID
ON Sites.Site_ID = Site_Project_Managers.Site_ID
WHERE (Sites.Completed = 0)
ORDER BY Sites.Site_Name

How to create a calculated column in a SQL Server 2008 table

I really need a calculated column on a table with simple sum.
Please see below:
SELECT key3
,SUM(UTOTALWBUD)
FROM CONTACT1
INNER JOIN CONTACT2
ON CONTACT1.ACCOUNTNO = CONTACT2.ACCOUNTNO
WHERE KEY1 = 'Client'
GROUP BY KEY3
I have tried to create a calculated column by adding following
ALTER TABLE ManagerTaLog
ADD WeeklyBudget as ( SELECT
key3
,SUM(UTOTALWBUD)
FROM CONTACT1
JOIN CONTACT2
ON CONTACT1.ACCOUNTNO = CONTACT2.ACCOUNTNO
WHERE KEY1 = 'Client'
GROUP BY KEY3)
I got the error message:
Msg 1046, Level 15, State 1, Line 4
Subqueries are not allowed in this context. Only scalar expressions are allowed.
Please advise what can I do about it.
Many thanks
Part 2
I have create a function; however, i get null values please advise.
CREATE FUNCTION [dbo].[SumIt](#Key3 varchar)
RETURNS TABLE
AS
RETURN
(
SELECT SUM(UTOTALWBUD)
FROM CONTACT1
JOIN CONTACT2
ON CONTACT1.ACCOUNTNO = CONTACT2.ACCOUNTNO
JOIN Phone_List
ON CONTACT1.KEY3 = Phone_List.[Manager ]
WHERE KEY1 = 'Client'
AND Phone_List.[Manager ] = #Key3
GROUP BY [Manager ]
)
END
GO
Just select statment that returns values I wish to add to Phone_list table
SELECT [Manager ]
,SUM(UTOTALWBUD)
FROM CONTACT1
JOIN CONTACT2
ON CONTACT1.ACCOUNTNO = CONTACT2.ACCOUNTNO
JOIN Phone_List
ON CONTACT1.KEY3 = Phone_List.[Manager ]
WHERE KEY1 = 'Client'
GROUP BY [Manager ]
Table definitions
CREATE TABLE [dbo].[CONTACT1](
[ACCOUNTNO] [varchar](20) NOT NULL,
[COMPANY] [varchar](40) NULL,
[CONTACT] [varchar](40) NULL,
[LASTNAME] [varchar](15) NULL,
[DEPARTMENT] [varchar](35) NULL,
[TITLE] [varchar](35) NULL,
[SECR] [varchar](20) NULL,
[PHONE1] [varchar](25) NOT NULL,
[PHONE2] [varchar](25) NULL,
[PHONE3] [varchar](25) NULL,
[FAX] [varchar](25) NULL,
[EXT1] [varchar](6) NULL,
[EXT2] [varchar](6) NULL,
[EXT3] [varchar](6) NULL,
[EXT4] [varchar](6) NULL,
[ADDRESS1] [varchar](40) NULL,
[ADDRESS2] [varchar](40) NULL,
[ADDRESS3] [varchar](40) NULL,
[CITY] [varchar](30) NULL,
[STATE] [varchar](20) NULL,
[ZIP] [varchar](10) NOT NULL,
[COUNTRY] [varchar](20) NULL,
[DEAR] [varchar](20) NULL,
[SOURCE] [varchar](20) NULL,
[KEY1] [varchar](20) NULL,
[KEY2] [varchar](20) NULL,
[KEY3] [varchar](20) NULL,
[KEY4] [varchar](20) NULL,
[KEY5] [varchar](20) NULL,
[STATUS] [varchar](3) NOT NULL,
[NOTES] [text] NULL,
[MERGECODES] [varchar](20) NULL,
[CREATEBY] [varchar](8) NULL,
[CREATEON] [datetime] NULL,
[CREATEAT] [varchar](5) NULL,
[OWNER] [varchar](8) NOT NULL,
[LASTUSER] [varchar](8) NULL,
[LASTDATE] [datetime] NULL,
[LASTTIME] [varchar](5) NULL,
[U_COMPANY] [varchar](40) NOT NULL,
[U_CONTACT] [varchar](40) NOT NULL,
[U_LASTNAME] [varchar](15) NOT NULL,
[U_CITY] [varchar](30) NOT NULL,
[U_STATE] [varchar](20) NOT NULL,
[U_COUNTRY] [varchar](20) NOT NULL,
[U_KEY1] [varchar](20) NOT NULL,
[U_KEY2] [varchar](20) NOT NULL,
[U_KEY3] [varchar](20) NOT NULL,
[U_KEY4] [varchar](20) NOT NULL,
[U_KEY5] [varchar](20) NOT NULL,
[recid] [varchar](15) NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[Phone_List](
[Manager ] [nvarchar](255) NULL,
[SalesCode] [nvarchar](255) NULL,
[Email] [nvarchar](255) NULL,
[PayrollCode] [nvarchar](255) NULL,
[Mobile] [nvarchar](255) NULL,
[FName] [nchar](20) NULL,
[idd] [tinyint] NULL,
[OD] [varchar](20) NULL,
[WeeklyBudget] AS ([dbo].[SumIt]([manager]))
) ON [PRIMARY]
You can wrap your query into the function like this (it HAS to return one value):
CREATE FUNCTION dbo.SumIt(#Key1 varchar(max))
returns float
as
begin
return (select sum(UTOTALWBUD) from
CONTACT1 inner join
CONTACT2 on
CONTACT1.ACCOUNTNO=CONTACT2.ACCOUNTNO
where KEY1=#key1
group by KEY3)
END
And use this function instead with calc field - something like this:
alter table ManagerTaLog add WeeklyBudget as dbo.SumIt(Key1)
NOTE
that it will be the performance killer for queries like that:
select * from ManagerTaLog
You should change your function in such a way, that is accept NOT varchar value, but NVARCHAR(255) - the same type as Manager column. Try it.
If you resolve the issue of returning two values, one solution would be to implement the calculation in a function and use this function for the calculated column.
Some considerations
I have assumed that it is Key3 that needs to be passed to the function and have added a where clause to return the weekly budget for the given Key3 value.
The function will get executed for every record in a resultset where you add the calculated column.
Script
CREATE FUNCTION dbo.fn_ManagerTaLogWeeklyBudget(#Key3 INTEGER) RETURNS INTEGER AS
BEGIN
select sum(UTOTALWBUD) from
CONTACT1 inner join
CONTACT2 on
CONTACT1.ACCOUNTNO=CONTACT2.ACCOUNTNO
where KEY1='Client'
AND KEY3 = #Key3
group by KEY3)
END
GO
ALTER TABLE dbo.ManagerTaLog
ADD WeeklyBudget AS dbo.fn_ManagerTaLogWeeklyBudget(Key3)
You cannot have a subquery that returns multiple values to be used as the computed column expression.
You can have an expression that returns a single value - or you can wrap your code in a stored function - or you can create a view (with a JOIN or subquery) that combines this logic into something you can use
IMHO It is a wrong way. You have to use trigger on CONTACT tables and update WeeklyBudget in these triggers.
You can have calculated columns in a table but that will be present (and calculated) in all rows of the table.
The thing what you're trying to do in your select is called "aggregate". Try this:
select key3, sum(UTOTALWBUD) as WeeklyBudget from
CONTACT1 inner join CONTACT2 on CONTACT1.ACCOUNTNO=CONTACT2.ACCOUNTNO
where KEY1='Client'
group by key3
CREATE FUNCTION [dbo].[SumIt](#Key3 varchar)
RETURNS TABLE
AS
RETURN
(
SELECT SUM(ISNULL(UTOTALWBUD,0))
FROM CONTACT1
JOIN CONTACT2
ON CONTACT1.ACCOUNTNO = CONTACT2.ACCOUNTNO
JOIN Phone_List
ON CONTACT1.KEY3 = Phone_List.[Manager ]
WHERE KEY1 = 'Client'
AND Phone_List.[Manager ] = #Key3
GROUP BY [Manager ]
)
END
GO
Hope this will help. Please note that this is not a proper solution, but this may help your particular scenario. Since the function is returning multiple values, you can either user a table valued function or just modify the query in a way that it will return only one value. But if the column is nullable please don't forget to add ISNULL.

Joining multiple columns in one table to a single column in another table

I am looking to create a view that pulls data from two tables "Schedule" and "Reference".
Schedule has 50+ columns (it's almost completely denormalized -- not my design), most of which contain a value that could be joined to a column in the Reference table.
How do I write the SQL statement to correctly join each column in Schedules to the single column in Reference?
The Schedule table is defined as:
CREATE TABLE [dbo].[Schedule](
[ID] [int] NOT NULL,
[SCHEDULEWEEK] [datetime] NOT NULL,
[EMPNO] [numeric](10, 0) NOT NULL,
[EMPLNAME] [varchar](32) NULL,
[EMPFNAME] [varchar](32) NULL,
[EMPSENDATE] [datetime] NULL,
[EMPHIREDATE] [datetime] NULL,
[EMPTYPE] [char](1) NULL,
[EMPSTATUS] [char](1) NULL,
[SNREFUSALS] [tinyint] NULL,
[QUALSTRING] [varchar](128) NULL,
[JOBOVERSHIFTTYPE] [bit] NULL,
[SHORTNOTICE] [bit] NULL,
[SHORTNOTICEWAP] [bit] NULL,
[SHORTNOTICEPHONE] [varchar](32) NULL,
[LEADHAND] [bit] NULL,
[DUALCURRENCY] [bit] NULL,
[MIN100WINDOW] [bit] NULL,
[STATHOLIDAY] [bit] NULL,
[AREAOVERHOURS] [bit] NULL,
[DOUBLEINTERZONES] [bit] NULL,
[MAXDAYSPERWEEK] [tinyint] NULL,
[MAXHOURSPERWEEK] [numeric](10, 2) NULL,
[MAXHOURSPERSHIFT] [numeric](10, 2) NULL,
[MAXDOUBLESPERWEEK] [tinyint] NULL,
[ASSIGNEDDAYS] [tinyint] NULL,
[ASSIGNEDHOURS] [numeric](10, 2) NULL,
[ASSIGNEDDOUBLES] [tinyint] NULL,
[ASSIGNEDLOAHOURS] [numeric](10, 2) NULL,
[SHIFTNO1] [int] NULL,
[TEXT1_1] [varchar](64) NULL,
[TEXT2_1] [varchar](64) NULL,
[DAYFLAG1] [bit] NULL,
[COMMENT1] [text] NULL,
[SHIFTNO2] [int] NULL,
[TEXT1_2] [varchar](64) NULL,
[TEXT2_2] [varchar](64) NULL,
[DAYFLAG2] [bit] NULL,
[COMMENT2] [text] NULL,
[SHIFTNO3] [int] NULL,
[TEXT1_3] [varchar](64) NULL,
[TEXT2_3] [varchar](64) NULL,
[DAYFLAG3] [bit] NULL,
[COMMENT3] [text] NULL,
[SHIFTNO4] [int] NULL,
[TEXT1_4] [varchar](64) NULL,
[TEXT2_4] [varchar](64) NULL,
[DAYFLAG4] [bit] NULL,
[COMMENT4] [text] NULL,
[SHIFTNO5] [int] NULL,
[TEXT1_5] [varchar](64) NULL,
[TEXT2_5] [varchar](64) NULL,
[DAYFLAG5] [bit] NULL,
[COMMENT5] [text] NULL,
[SHIFTNO6] [int] NULL,
[TEXT1_6] [varchar](64) NULL,
[TEXT2_6] [varchar](64) NULL,
[DAYFLAG6] [bit] NULL,
[COMMENT6] [text] NULL
-- Snip
) ON [PRIMARY]
And the Reference table is defined as:
CREATE TABLE [dbo].[Reference](
[ID] [int] NOT NULL,
[CODE] [varchar](21) NOT NULL,
[LOCATIONCODE] [varchar](4) NOT NULL,
[SCHAREACODE] [varchar](16) NOT NULL,
[LOCATIONNAME] [varchar](32) NOT NULL,
[FLTAREACODE] [varchar](16) NOT NULL
) ON [PRIMARY]
I am trying to join each [TEXT1_]/[TEXT2_] column in Schedule to the [SCHAREACODE] column in reference. All the reference table contains is a list of areas where the employee could work.
I think he means to join on the Reference table multiple times:
SELECT *
FROM Schedule AS S
INNER JOIN Reference AS R1
ON R1.ID = S.FirstID
INNER JOIN Reference AS R2
ON R2.ID = S.SecondID
INNER JOIN Reference AS R3
ON R3.ID = S.ThirdID
INNER JOIN Reference AS R4
ON R4.ID = S.ForthID
Your description is a bit lacking, so I'm going to assume that
Schedule has 50+ columns (it's almost completely denormalized -- not my design), most of which contain a value that could be joined to a column in the Reference table.
means that 1 of the 50+ columns in Schedule is a ReferenceId. So, given a table design like:
Schedule ( MaybeReferenceId1, MaybeReferenceId2, MaybeReferenceId3, ... )
Reference ( ReferenceId )
Something like:
SELECT *
FROM Schedule
JOIN Reference ON
Schedule.MaybeReferenceId1 = Reference.ReferenceId
OR Schedule.MaybeReferenceId2 = Reference.ReferenceId
OR Schedule.MaybeReferenceId3 = Reference.ReferenceId
OR Schedule.MaybeReferenceId4 = Reference.ReferenceId
...
would work. You could simplify it by using IN if your RDBMS supports it:
SELECT *
FROM Schedule
JOIN Reference ON
Reference.ReferenceId IN (
Schedule.MaybeReferenceId1,
Schedule.MaybeReferenceId2,
Schedule.MaybeReferenceId3,
Schedule.MaybeReferenceId4,
...
)
From updated question
Perhaps something like this? It will be messy no matter what you do.
SELECT S.ID
S.TEXT1_1,
TEXT1_1_RID = COALESCE((SELECT MAX(R.ID) FROM Reference R WHERE R.SCHAREACODE = S.TEXT1_1), 0),
S.TEXT1_2,
TEXT1_2_RID = COALESCE((SELECT MAX(R.ID) FROM Reference R WHERE R.SCHAREACODE = S.TEXT1_2), 0),
...
FROM Schedule S
Agree with TheSoftwareJedi, but can I just suggest using LEFT JOINs so that failures-to-match don't cause your Schedule row to disappear?
Of course, doing 28 JOINs is going to be a bit cumbersome whatever the details.
I'm not sure I'd call this "denormalized", more "abnormalized" ... :-)
Try a query like this:
select s.*, r.schareacode from schedule s,
where
s.text1_1 = s.schareacode
or s.text2_1 = s.schareacode
or s.textx_x = s.schareacode
..
You should be able to get the same results with traditional joins so I recommend you experiment with that as well.