I'm new to SQL and I'm trying to rewrite this query so that it uses a join instead of a union
DECLARE #user VARCHAR(255) = 'jSmith'
DECLARE #dept VARCHAR(255) = 'produce'
SELECT DISTINCT A.*
FROM goals A
INNER JOIN managers B ON B.name = #user
WHERE #user IN (A.userName,A.managerUserName)
AND dept = #dept
AND yr = '2016'
UNION
SELECT DISTINCT A.*
FROM goals A
INNER JOIN managers C ON C.name = #user
INNER JOIN committedGoals B ON A.goalID = B.goalID
WHERE dept LIKE #dept + '%'
AND yr = '2016'
This is not exactly the same because you've restricted the second part of the query to records that contain a record in committedGoals, but if you always have a record, then this might work for you:
SELECT g.*
FROM goals g
LEFT JOIN managers m
ON g.managerUserName=m.name
WHERE dept LIKE #dept + '%'
AND yr='2016'
AND (g.managerUserName=#user OR m.name=#user)
Related
This question already has an answer here:
SQL Server recursive self join
(1 answer)
Closed 3 years ago.
I have a SQL Server table that holds groups and subgroups that I am using to define user permissions in application. What I am trying to accomplish is to select all users ids from all subgroups based on used id assigned to group.
I have tried with this query but it only shows one level of subgroup users.
SET #UserIds =
ISNULL(
STUFF((SELECT ',' + CAST(tbl.UserID AS VARCHAR(MAX))
FROM
(SELECT grpUser.UserId AS UserID
FROM dbo.GroupUser grpUser
INNER JOIN (SELECT subGrp.Id, subGrp.GroupName
FROM dbo.Groups grp
INNER JOIN dbo.GroupUser guser ON grp.Id = guser.GroupId
AND guser.UserId = #UserId
INNER JOIN dbo.Groups subGrp ON grp.Id = subGrp.ParentGroupId) tbl ON grpUser.GroupId = tbl.Id) AS tbl
FOR XML PATH('')), 1, 1, ''), '')
I am struggling to get users ids in all subgroups. Number of subgroups is not defined. Is there a way to do in sql or should I shift this part to application side? Thank you for any advice.
Finally I came up with this code. Thank you for hint.
declare #UserGroupId int;
Set #UserGroupId = (Select GroupId from GroupUser gu
left join dbo.Groups gr on gu.GroupId = gr.id
where UserId = #UserId and gr.IsDeleted = 0)
declare #UsersGroups Table (
Id int not null,
GroupName nvarchar(50) not null
)
;WITH grp AS
(
SELECT Id, GroupName
FROM Groups
WHERE ParentGroupId = 1
UNION ALL
SELECT g.Id, g.GroupName
FROM Groups g
INNER JOIN dbo.GroupUser guser ON g.Id = guser.GroupId
INNER JOIN grp ON g.ParentGroupId = grp.Id
)
Insert into #UsersGroups
SELECT Id, GroupName
FROM grp
SET #UserIds = ISNULL(STUFF(( SELECT ',' + CAST(tbl.UserID AS VARCHAR(max)) FROM (
SELECT grpUser.UserId AS UserID FROM dbo.GroupUser grpUser
INNER JOIN ( SELECT * FROM #UsersGroups
) tbl ON grpUser.GroupId = tbl.Id
) AS tbl FOR XML PATH('') ), 1, 1, ''), '')
I'm creating a report in SSRS and want to have a multiple value parameter but allow blank values (''), and display all records when blank.
The gist of it is:
SELECT *
FROM Products p
JOIN ProductCategories c on c.ProductId = p.Id
WHERE (c.Name IN (#Categories) OR #Categories = '')
Which works when blank, and works with 1 category, but errors out with 2 categories. We got around this by using a temp table, but that solution seemed sort of hacky, so I wanted to see if there was a better way to resolve this.
The temp table workaround we built was this:
CREATE TABLE #temp (ProductId INT, Category NVARCHAR(MAX))
INSERT INTO #temp
SELECT p.Id, c.Name
FROM Products p
JOIN ProductCategories c on c.ProductId = p.Id
WHERE c.Name IN (#Categories)
IF ((SELECT COUNT(*) FROM #temp) = 0)
BEGIN
INSERT INTO #temp
SELECT p.Id, c.Name
FROM Products p
JOIN ProductCategories c on c.ProductId = p.Id
WHERE c.Name LIKE '%'
END
SELECT * FROM #temp
Thanks in advance!
If you don't have a split/parse function
Example
...
Where #Categories = ''
or
C.Name in (
Select RetVal = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace(#Categories,',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
)
Here is a dbFiddle ... You'll notice Poultry was excluded, then try it when #Categories=''
I have a table with the following fiels: PicklistTable, PicklistColumnName, FormTable and FormColumnName. FormColumnName is a foreign key into PicklistTable that I need to join on PicklistColumnName. Basically I need to find out how many times each picklist values has been used on all forms that reference that picklist. So the query would look something like this (maybe??):
SELECT PicklistColumnName, count(FormColumnName1) + count(FormColumnName2) as Count
FROM PicklistTable
INNER JOIN FormTable1 ON PicklistColumnName = FormColumnName1
INNER JOIN FormTable2 ON PicklistColumnName = FormColumnName2
GROUP BY PicklistColumnName
Here is an example table:
PicklistTable PicklistColumnName FormTable FormColumnName
tblEthnicityValues Ethnicity_ID tblContact Contact_Ethnicity_ID
tblEthnicityValues Ethnicity_ID udfOHFTCYPLACIHAC FatherEthnicityID
tblEthnicityValues Ethnicity_ID udfOHFTCYPLACIHAC MotherEthnicityID
tblEthnicityValues Ethnicity_ID udfOHFTCYPLACIHAYP EthnicityID
tblEthnicityValues Ethnicity_ID udfOHFTCYPLACIHAYP FatherEthnicityID
tblEthnicityValues Ethnicity_ID udfOHFTCYPLACIHAYP MotherEthnicityID
tblEthnicityValues Ethnicity_ID udfOHFTCYPLACRHAC FatherEthnicityID
tblEthnicityValues Ethnicity_ID udfOHFTCYPLACRHAC MotherEthnicityID
So I would in this case need to join tblContact, udfOHFTCYPLACIHAC etc on Contact_Ethnicity_ID, FatherEthnicityID etc.
Can someone please help? I hope I explained it well enough.
Thanks!
Tanya
Assuming that the PicklistColumnName from PicklistTable table need not be present in both FormTable1 and FormTable2 tables, this query might solve your problem.
SELECT pt.PicklistColumnName, count(ft1.FormColumnName1) + count(ft2.FormColumnName2) as Count
FROM PicklistTable pt
LEFT OUTER JOIN FormTable1 ft1
ON pt.PicklistColumnName = ft1.FormColumnName1
LEFT OUTER JOIN FormTable2 ft2
ON pt.PicklistColumnName = ft2.FormColumnName2
GROUP BY pt.PicklistColumnName
Do you want to get the following SQL:
DECLARE #tb TABLE(PicklistTable VARCHAR(30),PicklistColumnName VARCHAR(30),FormTable VARCHAR(30),FormColumnName VARCHAR(30) )
INSERT INTO #tb(PicklistTable,PicklistColumnName,FormTable,FormColumnName)
SELECT 'tblEthnicityValues','Ethnicity_ID','tblContact','Contact_Ethnicity_ID' UNION
SELECT 'tblEthnicityValues','Ethnicity_ID','udfOHFTCYPLACIHAC','FatherEthnicityID' UNION
SELECT 'tblEthnicityValues','Ethnicity_ID','udfOHFTCYPLACIHAC','MotherEthnicityID' UNION
SELECT 'tblEthnicityValues','Ethnicity_ID','udfOHFTCYPLACIHAYP','EthnicityID' UNION
SELECT 'tblEthnicityValues','Ethnicity_ID','udfOHFTCYPLACIHAYP','FatherEthnicityID' UNION
SELECT 'tblEthnicityValues','Ethnicity_ID','udfOHFTCYPLACIHAYP','MotherEthnicityID' UNION
SELECT 'tblEthnicityValues','Ethnicity_ID','udfOHFTCYPLACRHAC','FatherEthnicityID' UNION
SELECT 'tblEthnicityValues','Ethnicity_ID','udfOHFTCYPLACRHAC','MotherEthnicityID'
DECLARE #sql VARCHAR(max)
SELECT #sql='SELECT '+t.PicklistColumnName+',(0'+t.subCountSQL+') AS'+CHAR(13)+'Count FROM '+t.PicklistTable+CHAR(13)+t.subSQL FROM (
SELECT DISTINCT PicklistTable,PicklistColumnName,t2.* ,t3.*
FROM #tb AS t1
CROSS APPLY(SELECT 'INNER JOIN '+FormTable+' ON PicklistColumnName='+tt.FormTable+'.'+tt.FormColumnName+' '
FROM #tb AS tt WHERE tt.PicklistTable=t1.PicklistTable AND tt.PicklistColumnName=t1.PicklistColumnName
FOR XML PATH('')
) AS t2(subSQL)
CROSS APPLY(SELECT '+COUNT('+tt.FormTable+'.'+tt.FormColumnName +')'
FROM #tb AS tt WHERE tt.PicklistTable=t1.PicklistTable AND tt.PicklistColumnName=t1.PicklistColumnName
FOR XML PATH('')
) AS t3(subCountSQL)
)AS t
PRINT #sql
EXEC(#SQL)
The variable #SQL will be :
SELECT Ethnicity_ID,(0+COUNT(tblContact.Contact_Ethnicity_ID)+COUNT(udfOHFTCYPLACIHAC.FatherEthnicityID)+COUNT(udfOHFTCYPLACIHAC.MotherEthnicityID)+COUNT(udfOHFTCYPLACIHAYP.EthnicityID)+COUNT(udfOHFTCYPLACIHAYP.FatherEthnicityID)+COUNT(udfOHFTCYPLACIHAYP.MotherEthnicityID)+COUNT(udfOHFTCYPLACRHAC.FatherEthnicityID)+COUNT(udfOHFTCYPLACRHAC.MotherEthnicityID)) AS Count FROM tblEthnicityValues
INNER JOIN tblContact ON PicklistColumnName=tblContact.Contact_Ethnicity_ID INNER JOIN udfOHFTCYPLACIHAC ON PicklistColumnName=udfOHFTCYPLACIHAC.FatherEthnicityID INNER JOIN udfOHFTCYPLACIHAC ON PicklistColumnName=udfOHFTCYPLACIHAC.MotherEthnicityID INNER JOIN udfOHFTCYPLACIHAYP ON PicklistColumnName=udfOHFTCYPLACIHAYP.EthnicityID INNER JOIN udfOHFTCYPLACIHAYP ON PicklistColumnName=udfOHFTCYPLACIHAYP.FatherEthnicityID INNER JOIN udfOHFTCYPLACIHAYP ON PicklistColumnName=udfOHFTCYPLACIHAYP.MotherEthnicityID INNER JOIN udfOHFTCYPLACRHAC ON PicklistColumnName=udfOHFTCYPLACRHAC.FatherEthnicityID INNER JOIN udfOHFTCYPLACRHAC ON PicklistColumnName=udfOHFTCYPLACRHAC.MotherEthnicityID
What are other ways to get the same result set
I am using 4 tables
SELECT * FROM Terminal
SELECT * FROM Customer
SELECT * FROM Contract
SELECT * FROM ExternalTable
Data in these 4 tables are as below:
The query that i've written is
select ex.TerminalName,ex.CustomerName from ExternalTable ex
except
select t.TerminalName,ct.CustomerName from [Contract] c
inner join Terminal t on t.TerminalID=c.TerminalID
inner join Customer ct on ct.CustomerId=c.CustomerId
Which gets the below result
So just curious to know what are the other ways to get this same result
I'm not really what you are looking for, but here is another way to write the query that should produce the same results:
SELECT
ex.TerminalName,
ex.CustomerName
FROM
ExternalTable ex
WHERE
NOT EXISTS( SELECT
NULL
FROM
[Contract] c
INNER JOIN
Terminal t on t.TerminalID = c.TerminalID
INNER JOIN
Customer ct on ct.CustomerId = c.CustomerId
WHERE
t.TerminalName = ex.TerminalName
AND
ex.CustomerName = ct.CustomerName
)
This ought to be equivalent:
select ex.TerminalName,ex.CustomerName
from
ExternalTable ex
left outer join
(
[Contract] c
inner join Terminal t
on t.TerminalID=c.TerminalID
inner join Customer ct
on ct.CustomerId=c.CustomerId
)
on ex.TerminalName = t.TerminalName and ex.CustomerName = ct.CustomerName
where t.TerminalName is null and ct.CustomerName is null
You should note that except returns distinct results and to be strictly equivalent I would need to specify select distinct.
Here is a self-contained example that shows two alternatives.
One uses NOT IN, and the other uses a LEFT OUTER JOIN, but they should be equivalent.
--set up temp tables with dummy data to replicate the issue
declare #Terminal table(terminalid int,terminalname nvarchar(100));
insert into #Terminal select 1,'Terminal1' union select 2,'Terminal2'
declare #Customer table(customerid int,customername nvarchar(100));
insert into #Customer select 1,'Customer1' union select 2,'Customer2';
declare #Contract table(contractid int,terminalid int,customerid int,contractname nvarchar(100));
insert into #Contract select 1,1,1,'Contract1';
declare #ExternalTable table(externalid int,terminalname nvarchar(100),customername nvarchar(100),contractname nvarchar(100));
insert into #ExternalTable select 1,'Terminal1','Customer1','Contract1' union select 2,'Terminal2','Customer1','Contract1'
--SELECT * FROM #Terminal
--SELECT * FROM #Customer
--SELECT * FROM #Contract
--SELECT * FROM #ExternalTable
--goal: show records that are in the external table, but are not fully linked in the other tables
--original
select ex.TerminalName,ex.CustomerName from #ExternalTable ex
except
select t.TerminalName,ct.CustomerName from #Contract c
inner join #Terminal t on t.TerminalID=c.TerminalID
inner join #Customer ct on ct.CustomerId=c.CustomerId
--revised (left outer join method)
select et.TerminalName,et.CustomerName
from
#ExternalTable et
left join (
select ex.externalid
from
#Contract c
inner join #Terminal t on t.TerminalID=c.TerminalID
inner join #Customer ct on ct.CustomerId=c.CustomerId
inner join #ExternalTable ex on ex.terminalname = t.terminalname and ex.customername = ct.customername
) excludes on excludes.externalid = et.externalid
where excludes.externalid is null
--revised ("not in" method)
select et.TerminalName,et.CustomerName
from
#ExternalTable et
where et.externalid not in(
select ex.externalid
from
#Contract c
inner join #Terminal t on t.TerminalID=c.TerminalID
inner join #Customer ct on ct.CustomerId=c.CustomerId
inner join #ExternalTable ex on ex.terminalname = t.terminalname and ex.customername = ct.customername
)
I want to get data historical and the production. My stored procedure is as follows:
ALTER PROCEDURE [dbo].[pCaRptACInactivas](
#CodAsesor VARCHAR(15),
#CodOficina VARCHAR(4))
AS
SET NOCOUNT ON
DECLARE #CodArbolConta VARCHAR(25)
IF #CodOficina = '%'
SET #CodArbolConta = '%'
ELSE
SELECT #CodArbolConta = CodArbolConta + '%' FROM tClOficinas WHERE CodOficina LIKE #CodOficina
SELECT
tabACInactivas.CodOficina,
tabACInactivas.NomOficina,
tabACInactivas.NomAsesor,
MAX(tabACInactivas.CodPrestamo) CodPrestamo,
tabACInactivas.CodAsociacion,
tabACInactivas.NombreAsociacion,
MAX(tabACInactivas.Ciclo) AS Ciclo,
COUNT(DISTINCT tabACInactivas.CodUsuario) AS CantSocias,
MAX(tabACInactivas.FechaEstado) AS FechaCancelacion--,
FROM ( SELECT tClOficinas.CodOficina, tClOficinas.NomOficina, tCaClAsesores.CodAsesor, tCaClAsesores.NomAsesor, tCaPrestamos.CodPrestamo, tCaAsociacion.CodAsociacion, tCaAsociacion.NombreAsociacion, tCaPrestamos.Ciclo, tCaPrCliente.CodUsuario, tCaPrestamos.FechaEstado, tClParametros.FechaProceso FROM tCaPrestamos WITH(NOLOCK) INNER JOIN tCaProducto WITH(NOLOCK) ON tCaProducto.CodProducto = tCaPrestamos.CodProducto INNER JOIN tClOficinas WITH(NOLOCK) ON tClOficinas.CodOficina = tCaPrestamos.CodOficina INNER JOIN tCaAsociacion WITH(NOLOCK) ON tCaAsociacion.CodAsociacion = tCaPrestamos.CodAsociacion INNER JOIN tCaPrCliente WITH(NOLOCK) ON tCaPrCliente.CodPrestamo = tCaPrestamos.CodPrestamo INNER JOIN tClParametros WITH(NOLOCK) ON tClParametros.CodOficina = tClOficinas.CodOficina INNER JOIN tCaClAsesores ON tCaClAsesores.CodAsesor = tCaAsociacion.CodAsesor WHERE tCaPrestamos.Estado = 'CANCELADO' AND DATEDIFF(DAY, tCaPrestamos.FechaEstado, tClParametros.FechaProceso) > 30 AND NOT EXISTS(SELECT 1
FROM tCaPrestamos Pr
INNER JOIN tCaPrCliente PrCl ON PrCl.CodPrestamo = Pr.CodPrestamo
WHERE Pr.Estado NOT IN ('TRAMITE', 'APROBADO')
AND Pr.FechaDesembolso >= tCaPrestamos.FechaEstado
AND Pr.CodAsociacion = tCaPrestamos.CodAsociacion
) AND tCaProducto.Tecnologia = 3 AND tCaPrestamos.CodAsesor LIKE #CodAsesor AND tCaPrestamos.CodOficina IN (SELECT CodOficina FROM tClOficinas WHERE CodArbolConta LIKE #CodArbolConta)
UNION ALL
SELECT tClOficinas.CodOficina, tClOficinas.NomOficina, tCaClAsesores.CodAsesor, tCaClAsesores.NomAsesor, tCaHPrestamos.CodPrestamo, tCaAsociacion.CodAsociacion, tCaAsociacion.NombreAsociacion, tCaHPrestamos.Ciclo, tCaHPrCliente.CodUsuario, tCaHPrestamos.FechaEstado, tClParametros.FechaProceso FROM tCaHPrestamos WITH(NOLOCK) INNER JOIN tCaProducto WITH(NOLOCK) ON tCaProducto.CodProducto = tCaHPrestamos.CodProducto INNER JOIN tClOficinas WITH(NOLOCK) ON tClOficinas.CodOficina = tCaHPrestamos.CodOficina INNER JOIN tCaAsociacion WITH(NOLOCK) ON tCaAsociacion.CodAsociacion = tCaHPrestamos.CodAsociacion INNER JOIN tCaHPrCliente WITH(NOLOCK) ON tCaHPrCliente.CodPrestamo = tCaHPrestamos.CodPrestamo INNER JOIN tClParametros WITH(NOLOCK) ON tClParametros.CodOficina = tClOficinas.CodOficina INNER JOIN tCaClAsesores ON tCaClAsesores.CodAsesor = tCaAsociacion.CodAsesor WHERE tCaHPrestamos.Estado = 'CANCELADO' AND DATEDIFF(DAY, tCaHPrestamos.FechaEstado, tClParametros.FechaProceso) > 30 AND NOT EXISTS(SELECT 1
FROM tCaHPrestamos Pr
INNER JOIN tCaHPrCliente PrCl ON PrCl.CodPrestamo = Pr.CodPrestamo
WHERE Pr.Estado NOT IN ('TRAMITE', 'APROBADO')
AND Pr.FechaDesembolso >= tCaHPrestamos.FechaEstado
AND Pr.CodAsociacion = tCaHPrestamos.CodAsociacion
) AND tCaProducto.Tecnologia = 3 AND tCaHPrestamos.CodAsesor LIKE #CodAsesor AND tCaHPrestamos.CodOficina IN (SELECT CodOficina FROM tClOficinas WHERE CodArbolConta LIKE #CodArbolConta)
)tabACInactivas
GROUP BY tabACInactivas.CodAsociacion, tabACInactivas.NombreAsociacion, tabACInactivas.NomOficina, tabACInactivas.CodOficina, tabACInactivas.NomAsesor
I want the CantSocias column takes the most value of the Ciclo column, but not working
That stored procedure that you have posted up is way too large and blocky to even try to interpret and understand. So I will go off of your last sentence:
I want the CantSocias column takes the most value of the Ciclo column,
but not working
Basically if you want to set a specific column to that, you can do something like this:
update YourTable
set CantSocias =
(
select max(Ciclo)
from YourOtherTable
)
-- here is where you can put a conditional WHERE clause
You may need to create a sub query to get the most value of Ciclo and join back to your query.
An example of what I mean is here:
create table #Product
(
ID int,
ProductName varchar(20)
)
insert into #Product(ID, ProductName)
select 1,'ProductOne'
union
select 2,'ProductTwo'
create table #ProductSale
(
ProductID int,
Number int,
SalesRegion varchar(20)
)
insert into #ProductSale(ProductID,Number,SalesRegion)
select 1,1500,'North'
union
select 1, 1200, 'South'
union
select 2,2500,'North'
union
select 2, 3200, 'South'
--select product sales region with the most sales
select * from #Product p
select ProductId, Max(Number) as Bestsale from #ProductSale ps group by ProductID
--combining
select
p.ID,
p.ProductName,
tp.Bestsale,
ps.SalesRegion
from
#Product p
inner join
(select ProductId, Max(Number) as Bestsale from #ProductSale ps group by ProductID) as tp on p.ID = tp.ProductID
inner join
#ProductSale ps on p.ID = ps.ProductID and tp.Bestsale = ps.Number