SQL Group by on outer reference after 2 inner joins - sql

My sql query is not working as intended, in its current form it will return results, but some of them on the second column are duplicated, or in other words, some the computer names followed by the drive letter show twice.
The query is this:
(select Distinct 'ServerDrive' as storageType, cast(assetname as
varchar)+ '\ ' +cast(caption as varchar) as storagePath,((rqDiskdrivesHist.
[size]-rqDiskdrivesHist.[freespace])/1024/1024) as usedMB,(rqDiskdrivesHist.
[size]/1024/1024) as sizeMB from lansweeperdb.dbo.tblAssets
inner join rqDiskdrivesHist
on lansweeperdb.dbo.tblAssets.AssetID=rqDiskdrivesHist.AssetID
where drivetype=3
and lansweeperdb.dbo.tblAssets.AssetName in
(select distinct entitypath from rqcentities
inner join rqcustomer
on rqcentities.customerID=rqcustomer.customerID
where customername like '%ak 26%' and entityType='computer'
and not (
(AssetName like 'WFP3675' and caption like 'D:')
or
(AssetName like 'WFP3675' and caption like 'E:')
or
(AssetName like 'WFP3675' and caption like 'F:')
or
(AssetName like '%00500%')
)
))
If I try to group by at the end. with:
GROUP BY cast(assetname as varchar)+'\'+cast(caption as varchar)
I will get the "Each GROUP BY expression must contain at least one column that is not an outer reference.
" error.
Edit: These are 2 rows from the results which are duplicated.

You need to group on the alias instead as you did not expose those fields in the inner query.
SELECT
storageType,
storagePath,
MaxMB = MAX(usedMB),
MinMB = MIN(usedMB),
AvgMB = AVG(usedMB)
FROM
(
select 'ServerDrive' as storageType,
cast(assetname as varchar)+ '\ ' +cast(caption as varchar) as storagePath,
((rqDiskdrivesHist.[size]-rqDiskdrivesHist.[freespace])/1024/1024) as usedMB,
(rqDiskdrivesHist.[size]/1024/1024) as sizeMB
from
lansweeperdb.dbo.tblAssets
inner join rqDiskdrivesHist on lansweeperdb.dbo.tblAssets.AssetID=rqDiskdrivesHist.AssetID
where
drivetype=3
and lansweeperdb.dbo.tblAssets.AssetName in
(
select distinct entitypath
from rqcentities
inner join rqcustomer on rqcentities.customerID=rqcustomer.customerID
where customername like '%ak 26%' and entityType='computer'
and not (
(AssetName like 'WFP3675' and caption like 'D:')
or
(AssetName like 'WFP3675' and caption like 'E:')
or
(AssetName like 'WFP3675' and caption like 'F:')
or
(AssetName like '%00500%')
)
)
) AS X
GROUP BY
storagePath,
storageType

Related

how to use LIKE instead of IN with multiple values?

I want to replace In with Like to make the query work.
SELECT
1 AS coddit, COD_CAT AS cam_cod, DES_CAT AS cam_desc,
LIVELLO_CAT AS livello, COD_CAT_PADRE AS cat_padre,
COD_L1, COD_L2, COD_L3, COD_L4, COD_L5, COD_L6
FROM
dbo.CLASS_ART
WHERE
1=1
AND TIPO_CLASS = 16 --B2B
AND LIVELLO_CAT = '0'
AND COD_CAT IN (SELECT DISTINCT CAT_MERCE.COD_CAT
FROM ART_LIST_PREZZI
INNER JOIN ART_ANA ON ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
INNER JOIN CAT_MERCE ON ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
AND ART_LIST_PREZZI.COD_LIST = 'EXPORT_002')
The comparison I would like to do with LIKE otherwise the query doesn't work well
the subquery returns more than one value and it is correct but if I use Like instead of IN I have this error message:
Query return more than 1 values
Using LIKE against a subquery that returns multiple records won't work. A solution would be to turn the IN condition to an EXISTS condition, like:
and exists (
select 1
from ART_LIST_PREZZI
inner join ART_ANA
on ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
inner join CAT_MERCE
on ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
and ART_LIST_PREZZI.COD_LIST = 'EXPORT_002'
where COD_CAT like '%' + CAT_MERCE.COD_CAT + '%'
)
Like has to be compared to a single string, so you need to set all your ids on a single string. You can do that using the for xml clause.
(SELECT DISTINCT CAST(CAT_MERCE.COD_CAT AS VARCHAR(32))
FROM ART_LIST_PREZZI
INNER JOIN ART_ANA ON ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
INNER JOIN CAT_MERCE ON ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
AND ART_LIST_PREZZI.COD_LIST = 'EXPORT_002'
FOR XML PATH(''))
Now I would delimite your ids by commas, so you don't find false positives, and compare it using like.
AND
(SELECT DISTINCT ',' + CAST(CAT_MERCE.COD_CAT AS VARCHAR(32)) + ','
FROM ART_LIST_PREZZI
INNER JOIN ART_ANA ON ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
INNER JOIN CAT_MERCE ON ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
AND ART_LIST_PREZZI.COD_LIST = 'EXPORT_002'
FOR XML PATH('')) LIKE '%,' + COD_CAT + ',%'
This would work, and you would have changed your IN operator with a LIKE operator, but I don't see the point of it, its performance would be worse than your original query.
Use EXISTS:
EXISTS (SELECT 1
FROM ART_LIST_PREZZI LP JOIN
ART_ANA A
ON LP.COD_ART = A.COD_ART JOIN
CAT_MERCE M
ON A.COD_CAT = M.COD_CAT AND
LP.COD_LIST = 'EXPORT_002' AND
CLASS_ART.COD_CAT LIKE M.COD_CAT
)
I assume that the logic you actually want uses wildcards:
CLASS_ART.COD_CAT LIKE CONCAT('%', M.COD_CAT, '%')
If so, it suggests an issue with the data model. Why would two columns with the same name (COD_CAT) need to be joined using LIKE instead of =.

SQL LIKE is only working With Full Name

In one of my sp I have following lines of code
select distinct (a.itemid), a.itemcode, v.itemdescription
from aitem a
INNER JOIN vwitemdescription v ON a.itemID = v.itemID
WHERE a.active=1
-----------------------------------------
AND (#ItemDesc like '%'+ a.itemdescription +'%')
-----------------------------------------
If I give #ItemDesc value in full description, I get values and if I give #ItemDesc value in half description I get nothing in return.
For Example :
If I giv
#ItemDesc = 'Cow Dung - '
I get result as
---------------------------------------
|itemid | itemcode | itemdescription |
--------------------------------------
| 63 | 40-17005 | Cow Dung - |
---------------------------------------
And even if I cut the string as #ItemDesc = 'Cow Dung' I get the same results,
But if I cut it into #ItemDesc = 'Cow' or only to single character I don't get any results.
I want to load the item even if I enter only a single charecter in it.
Is there anything wrong with my code? How to get it right?
You need to switch the items in your LIKE expression:
AND a.itemdescription LIKE '%' + #ItemDesc + '%'
Using this logic, any substring of the itemdescription would match. For example the following is a true condition:
AND `Cow Dung - ` LIKE '%Cow%'
Here is the full query:
SELECT DISTINCT
a.itemid, a.itemcode, v.itemdescription
FROM aitem a
INNER JOIN vwitemdescription v
ON a.itemID = v.itemID
WHERE
a.active = 1 AND
a.itemdescription LIKE '%' + #ItemDesc + '%';
Comparison variable should be always at the right side of the statement. Your new query should be as below.
select distinct (a.itemid), a.itemcode, v.itemdescription
from aitem a
INNER JOIN vwitemdescription v ON a.itemID = v.itemID
WHERE a.active=1
--changed condition start
AND (a.itemdescription like '%'+ #ItemDesc +'%')
--changed condition end

Getting "replicated" values

So I have two tables: Agent and Conta.
Agents can have a lot of Conta but one Conta can only have one Agent.
I want to display just the Agents, to create a html table where you can see all of the agents present in the database - on a backoffice!
I'm using the following code, but the result I'm getting is one agent entry for each conta where he participated.
WITH LAST_COUNT AS
(SELECT {Conta}.[AgentId], {Conta}.[Data], {Conta}.[Valor],{Conta}.[Submit]
FROM {Conta})
SELECT
{Agent}.[Id], {Agent}.[Nome], {Agent}.[Apelido], LAST_COUNT.[Data],
LAST_COUNT.[Valor], LAST_COUNT.[Submit], {AgentPicture}.[Id],
{AgentPicture}.[Filename], {Agent}.[Telemovel], {Agent}.[UserId]
FROM {Agent}
LEFT JOIN {AgentPicture} ON {AgentPicture}.[Id] = {Agent}.[Id]
INNER JOIN LAST_COUNT ON LAST_COUNT.[AgentId] = {Agent}.[Id]
WHERE {Agent}.[Id] LIKE '%' + #SearchFilter + '%'
OR {Agent}.[Nome] LIKE '%' + #SearchFilter + '%'
OR {Agent}.[Apelido] LIKE '%' + #SearchFilter + '%'
OR #SearchFilter = ''
Can you help me? thanks!
In your query you are joining Agent table with LAST_COUNT common table expression (CTE). As a result you have every record from Contra in your results.
Just remove
WITH LAST_COUNT AS
(SELECT {Conta}.[AgentId], {Conta}.[Data], {Conta}.[Valor],{Conta}.[Submit]
FROM {Conta})
from your query and drop the last JOIN statement: LEFT JOIN LAST_COUNT ON LAST_COUNT.[AgentId] = {Agent}.[Id]
Also, do not forget to remove the following columns, which are retrieved from LAST_COUNT table:
LAST_COUNT.[Data],
LAST_COUNT.[Valor], LAST_COUNT.[Submit],

Complex Query Incorrect Syntax Error

I have tried to search for a solution to this but I have not been able to find one that fits this situation.
First I must say that my SQL is a lot rusty. The following query is the most complex one I have ever done to date.
Here is the query:
Declare #root varchar(Max)
set #root = ''
Select
ib.irrnum, ib.status, pu.probtype,
ib.submitby, ta.[Task Action], ib.area, co.cost,
rc.rootcause, ib.jobnum
From
tbl_irrbase ib
Left Join
tbl_cost co On ib.irrnum = co.irrnum
Left join
(Select Distinct probtype, irrnum
From tbl_probtype) pu On ib.irrnum = pu.irrnum
Left Join
(Select Distinct rootcause, irrnum
From tbl_rtcause) rc On ib.irrnum = rc.irrnum
Left Join
(Select TOP 1
(owner + Space(1) + Convert(varchar(10), senddate, 101) + Space(1) + taskitem) As 'Task Action',
irrnum
From
(select * From tbl_taskaction) ta
Order by
senddate Desc, sendtime Desc) ta On ib.irrnum = ta.irrnum
left Join
(Select [#root] = #root + rs.rootsource + Space(3), irrnum
From tbl_rtsource rs
Where rs.entrydate Between '10/04/2016' And '10/06/2016'
Select #root As 'Root Source') sr On ib.irrnum = sr.irrnum
Where
ib.submitedate between '09/28/2016' And '10/05/2016'
My problem is with the last Left Join line. If I take the entire Select statement out and run it in SSMS it runs fine, no errors. But when I try and run it in this query I get an error, red squiggly line under 'Select #root As' telling me the following:
Incorrect Syntax near 'Select'.
Expecting ')', EXCEPT, or UNION
I do not know how to fix this. If I remove this last 'Left Join' line the query runs fine.
Any ideas?
Instead of the last LEFT JOIN, try something like this:
CROSS APPLY (
SELECT (
SELECT rs.rootsource + Space(3)
From tbl_rtsource rs
Where rs.entrydate Between '10/04/2016' And '10/06/2016'
AND rs.irrnum=ib.irrnum
FOR XML PATH('')
) AS rootsource
) sr
Then include sr.rootsource in the columns of the first SELECT.

Conversion failed when converting the varchar value '_1' to data type int

Trying to run this query I wrote to return a list of files in a course, but running into this error that a conversion failed when converting the varchar value '_1' to data type int.
SELECT cm.course_id, cc.title title, cc.dtmodified dtmodified, MIN(xf.FILE_SIZE) file_size, MIN(crl.resource_id) resource_id, MIN(xu.FULL_PATH) full_path
FROM BBLEARN.dbo.cms_resource_link crl
INNER JOIN BBLEARN.dbo.course_contents cc ON cc.pk1 = crl.parent_pk1
INNER JOIN BBLEARN.dbo.course_main cm ON cm.pk1 = crl.crsmain_pk1
INNER JOIN BBLEARN.dbo.course_users cu ON cm.pk1 = cu.crsmain_pk1
INNER JOIN BBLEARN.dbo.users u ON cu.users_pk1 = u.pk1
INNER JOIN BBLEARN_CMS_DOC.dbo.XYF_FILES xf ON crl.resource_id = xf.ENTRY_ID + '_1'
INNER JOIN BBLEARN_CMS_DOC.dbo.XYF_URLS xu ON xu.FILE_ID = xf.FILE_ID
INNER JOIN BBLEARN_CMS_DOC.dbo.XYF_FILES xf2 ON xu.PARENT_ID = xf2.FILE_ID
WHERE crl.parent_data_type='content'
AND cu.role='P'
AND crl.storage_type='PUBLIC'
AND xf.FILE_TYPE_CODE='F'
AND (LOWER(xu.FILE_NAME) LIKE N'%.mov%' or LOWER(xu.FILE_NAME) LIKE N'%.avi%' or LOWER(xu.FILE_NAME) LIKE N'%.wm%' or LOWER(xu.FILE_NAME) LIKE N'%.mp%' or LOWER(xu.FILE_NAME) LIKE N'%.rm%' or LOWER(xu.FILE_NAME) LIKE N'%.flv%' or LOWER(xu.FILE_NAME) LIKE N'%.amr%' or LOWER(xu.FILE_NAME) LIKE N'%.aif%' or LOWER(xu.FILE_NAME) LIKE N'%.aup%' or LOWER(xu.FILE_NAME) LIKE N'%.m4%' or LOWER(xu.FILE_NAME) LIKE N'%.wav%' or LOWER(xu.FILE_NAME) LIKE N'%.swf%')
AND xu.FULL_PATH NOT LIKE '/internal/%'
AND NOT EXISTS (
SELECT 1 FROM BBLEARN.dbo.cms_resource_link
WHERE crsmain_pk1 = crl.crsmain_pk1
AND parent_pk1 = crl.parent_pk1
AND parent_data_type='content'
AND resource_id = xf2.ENTRY_ID + '_1' )
GROUP BY cm.course_id, cc.pk1, cc.title, cc.dtmodified ORDER BY 1;
Which shows up in line 7 and 21 I believe where there is the concatenation of xf.ENTRY_ID + '_1' and xf2.ENTRY_ID + '_1'
Since xf2.ENTRY_ID is an INT, SQL will not try to concatenate the values, but add them together. You need to explicitly cast the INT to a VARCHAR, or CHAR in order to concatenate them.
Change
AND resource_id = xf2.ENTRY_ID + '_1'
To
AND resource_id = CONVERT(VARCHAR(20),xf2.ENTRY_ID) + '_1'
And
INNER JOIN BBLEARN_CMS_DOC.dbo.XYF_FILES xf ON crl.resource_id = xf.ENTRY_ID + '_1'
To
INNER JOIN BBLEARN_CMS_DOC.dbo.XYF_FILES xf ON crl.resource_id = CONVERT(VARCHAR(20),xf.ENTRY_ID) + '_1'
I am defining a VARCHAR(20) as ENTRY_ID could be of BIGINT data type (though i think you should have way too much rows in order to need 20 digit long ids...
try this.You should cast xf.ENTRY_ID and xf2.ENTRY_ID in varchar type with appropirate range right now im using Max length for the same. Hope your code will work.
Like this:
cast(xf.ENTRY_ID varchar(max)) + '_1' and cast(xf2.ENTRY_ID as varchar(max)) + '_1'