How to use a dynamically created column in a WHERE clause - sql

I created a table column called name cause the firstname and the lastname are stored in two separate columns. To solve the problem I use CONCAT in the SELECT statement. However if I want to search for a specific value inside the name column SQL returns the error:
Unknown column 'name' in 'where clause'
Is it possible to search in a dynamically created column in a SELECT statement?
SELECT
u.ID AS id,
CONCAT(umFirstName.meta_value, " ", umLastName.meta_value) AS name,
u.user_email AS email,
umChatStatus.meta_value AS chatStatus,
umCallStatus.meta_value AS callStatus,
umRef.meta_value AS reference
FROM
wp_users AS u
LEFT JOIN
wp_usermeta AS um ON u.ID = um.user_id
LEFT JOIN
wp_usermeta AS umFirstName ON u.ID = umFirstName.user_id
AND umFirstName.meta_key = "_ctbFirstName"
LEFT JOIN
wp_usermeta AS umLastName ON u.ID = umLastName.user_id
AND umLastName.meta_key = "_ctbLastName"
LEFT JOIN
wp_usermeta AS umChatStatus ON u.ID = umChatStatus.user_id
AND umChatStatus.meta_key = "_ctbChatSessionStatus"
LEFT JOIN
wp_usermeta AS umCallStatus ON u.ID = umCallStatus.user_id
AND umCallStatus.meta_key = "_ctbCallSessionStatus"
LEFT JOIN
wp_usermeta AS umRef ON u.ID = umRef.user_id
AND umRef.meta_key = "_ctbRef"
WHERE
um.meta_key = "wp_capabilities"
AND um.meta_value IN ('a:1:{s:8:"employee ";b:1;}')
AND u.id LIKE '%%'
OR name LIKE '%%'
OR u.user_email LIKE '%%'
OR umChatStatus.meta_value LIKE '%%'
OR umCallStatus.meta_value LIKE '%%'
OR umRef.meta_value LIKE'%%'
ORDER BY
id DESC
LIMIT 0, 20
UPDATE
Got it working like it should. Thanks to Caius Jard metioning to -always use parentheses- in a AND and OR mix. For someone that is interested in the solution.

SQL queries are evaluated in the following order (just the blocks you've used):
FROM (including joins)
WHERE
SELECT
ORDER BY
This means that something you create in the SELECT, like CONCAT(Firstname, ' ', LastName) simply doesn't exist at the time the WHERE is evaluated
You have a couple of options:
Use CONCAT(Firstname, ' ', LastName) in the WHERE clause too
SELECT
CONCAT(Firstname, ' ', LastName) AS N
FROM
person
WHERE
CONCAT(Firstname, ' ', LastName) = 'John smith'
Turn the whole query into a sub query and use the thing you created in the outer
SELECT
x.N
FROM
(
SELECT
CONCAT(Firstname, ' ', LastName) AS N
FROM
person
) x
WHERE
x.N = 'John smith'
This form can also be written as:
WITH x AS
(
SELECT
CONCAT(Firstname, ' ', LastName) AS N
FROM
person
)
SELECT x.N
FROM x
WHERE x.N = 'John smith'
These latter forms are useful when you want to use it multiple times and don't want to keep repeating some massive calculation:
WITH x AS
(
SELECT
SUM(Points) / DATEDIFF(day, MIN(GameStart), MAX(GameEnd)) as PointsPerDay
FROM
Games
GROUP BY PlayerId
)
SELECT
CASE
WHEN PointsPerDay < 100 THEN 'Newbie'
WHEN PointsPerDay < 200 THEN 'Seasoned'
WHEN PointsPerDay < 300 THEN 'Advanced'
ELSE 'Pro'
END as Grading
FROM x
To have to keep repeating a calculation in order to do it all in one query is a bit ugly:
SELECT
CASE
WHEN SUM(Points) / DATEDIFF(day, MIN(GameStart), MAX(GameEnd)) < 100 THEN 'Newbie'
WHEN SUM(Points) / DATEDIFF(day, MIN(GameStart), MAX(GameEnd)) < 200 THEN 'Seasoned'
WHEN SUM(Points) / DATEDIFF(day, MIN(GameStart), MAX(GameEnd)) < 300 THEN 'Advanced'
ELSE 'Pro'
END as Grading
FROM
Games
GROUP BY PlayerId
And indeed because a GROUP BY is evaluated after a WHERE, if you want to use the result of a group by in a where you must do it as a "sub query that groups"/"outer query that wheres" pair

You can directly compare the concatenated value in the where clause like so:
CONCAT(umFirstName.meta_value, " ", umLastName.meta_value) LIKE '%abc%'
SELECT
u.ID AS id,
CONCAT(umFirstName.meta_value, " ", umLastName.meta_value) AS name,
u.user_email AS email,
umChatStatus.meta_value AS chatStatus,
umCallStatus.meta_value AS callStatus,
umRef.meta_value AS reference
FROM wp_users AS u
LEFT JOIN wp_usermeta AS um ON u.ID = um.user_id
LEFT JOIN wp_usermeta AS umFirstName ON u.ID = umFirstName.user_id AND
umFirstName.meta_key = "_ctbFirstName"
LEFT JOIN wp_usermeta AS umLastName ON u.ID = umLastName.user_id AND
umLastName.meta_key = "_ctbLastName"
LEFT JOIN wp_usermeta AS umChatStatus
ON u.ID = umChatStatus.user_id AND umChatStatus.meta_key = "_ctbChatSessionStatus"
LEFT JOIN wp_usermeta AS umCallStatus
ON u.ID = umCallStatus.user_id AND umCallStatus.meta_key = "_ctbCallSessionStatus"
LEFT JOIN wp_usermeta AS umRef ON u.ID = umRef.user_id AND umRef.meta_key = "_ctbRef"
WHERE um.meta_key = "wp_capabilities"
AND um.meta_value IN ('a:1:{s:8:"employee ";b:1;}')
AND u.id LIKE '%%'
OR CONCAT(umFirstName.meta_value, " ", umLastName.meta_value) LIKE '%%'
OR u.user_email LIKE '%%'
OR umChatStatus.meta_value LIKE '%%'
OR umCallStatus.meta_value LIKE '%%'
OR umRef.meta_value LIKE'%%'
ORDER BY id DESC
LIMIT 0, 20

Related

SQL Server : Pivot Table Odd result,

So, full disclosure, this is my first time using a pivot table and the result set has multiple columns as a result. In this example, we will use the result set without a pivot table applied.
This student has taken multiple courses. What the ideal end result would be, is to count how many courses this student has taken. So if I look I see that the Student has taken Algebra 1 5 times, English 1 2 times and Geometry 2 times.
The Next image is the query with the pivot applied, oh and to make things complicated, its a monster query before trying to attempt the pivot.
So we see in this, that Algebra 1 has a count of 0, Geometry has a count of 2 and English has a count of 0. This is the same query as before but just using this student.
Query:
SELECT *
FROM
(SELECT
[StudentNumber], psat.MathScaledScore, psat.EBRWScore,
SCReady.MathScaleScore, SCReady.ReadingScaleScore,
SpringMap.MathPercentile, SpringMap.ReadingPercentile,
Coursework.Course_name
FROM
[OnlineApplications].[dbo].[Users] U
LEFT JOIN
[OnlineApplications].[dbo].ContactInfoes C ON C.ContactInfoId = U.UserId
LEFT JOIN
(SELECT *
FROM [DOENRICH-SQL].[enrich_prod].dbo.HCS_view_Most_Recent_PSAT_Scores Scores) AS psat ON U.StudentNumber = psat.number
LEFT JOIN
(SELECT
stud.Number, sc.DateTaken,
CASE sc.ELALev
WHEN 'E8AE0E4D-AD36-41D8-AC89-627D19661803' THEN 'Exceeds Expectations'
WHEN 'C9F2CDA2-D904-438B-9DD3-94EFC9111A0E' THEN 'Approaches Expectations'
WHEN '9B39E28F-89C8-44AD-A8F2-1463192F88F1' THEN 'Does Not Meet Expectation'
WHEN '87247DB1-4A57-419E-9619-7B43B02B1135' THEN 'Meets Expectations'
END ELALev,
sc.ELASS AS ELAScaleScore, sc.elavss AS VerticalScaleScore,
sc.elassread AS ReadingScaleScore,
sc.ELARS10 AS RawScoreStandard10, sc.elASPR AS ELAStatePercentileRank,
MathLev = CASE MathLev
WHEN 'E8AE0E4D-AD36-41D8-AC89-627D19661803' THEN 'Exceeds Expectations'
WHEN 'C9F2CDA2-D904-438B-9DD3-94EFC9111A0E' THEN 'Approaches Expectations'
WHEN '9B39E28F-89C8-44AD-A8F2-1463192F88F1' THEN 'Does Not Meet Expectation'
WHEN '87247DB1-4A57-419E-9619-7B43B02B1135' THEN 'Meets Expectations'
END,
sc.MATHSS AS MathScaleScore, sc.MathVSS AS MathVerticalScaleScore,
sc.mathspr AS MathStatePercentileRank
FROM
[DOENRICH-SQL].[enrich_prod].dbo.t_sc_ready sc
JOIN
[DOENRICH-SQL].[enrich_prod].dbo.Student stud ON sc.StudentID = stud.ID
WHERE
DateTaken = '2019-05-17') AS SCReady ON SCReady.number = U.studentnumber
LEFT JOIN
(
select stud.Number, max(map.readingPercentile) as ReadingPercentile, max(map.mathPercentile) as MathPercentile
from [DOENRICH-SQL].[ENRICH_PROD].[dbo].t_map map
join [DOENRICH-SQL].[ENRICH_PROD].[INFORM].[Map_GradeLevelID] mapping on map.GradeLevelID = mapping.DestID
JOIN [DOENRICH-SQL].[ENRICH_PROD].[dbo].[Student] stud on map.StudentID = stud.ID
where DateTaken >= '2018-08-01'
group by stud.Number
) as SpringMap on SpringMap.number = U.Studentnumber
left join (
SELECT * FROM OPENQUERY(PSPROD,'
Select B.STUDENT_NUMBER , A.COURSE_NAME, A.GRADE_LEVEL, A.SCHOOLNAME, A.GRADE
from PS.STOREDGRADES A
join PS.STUDENTS B ON A.STUDENTID = B.ID
AND STORECODE in (''Q1'',''Q2'',''Q3'',''Q4'',''F1'')
AND (COURSE_NAME LIKE ''%Algebra 1%'' OR COURSE_NAME LIKE ''%Geometry Honors%'' OR COURSE_NAME LIKE ''%English 1%'')
group by B.STUDENT_NUMBER , A.COURSE_NAME, a.STORECODE, A.GRADE, A.PERCENT, A.GRADE_LEVEL, A.SCHOOLNAME
ORDER BY STUDENT_NUMBER, STORECODE DESC
'
)
) as Coursework on Coursework.STUDENT_NUMBER = U.StudentNumber
join [OnlineApplications].[dbo].ScholarsApps Sapps on Sapps.ScholarsAppId = u.UserId
where AppYear = 2019 and StudentNumber <> '' and StudentNumber = '17476'
) T
PIVOT (
COUNT (COURSE_NAME)
FOR course_name IN (
[Algebra 1],
[Geometry Honors],
[English 1])
)
as Pivot_table
Again, very complicated query before and I'm not clear if I'm using the pivot function correctly.
I'd love to have this pivot with the counts of the courses.

CTE to find duplicates?

Can someone show me how i would add to this CTE to include the column 'Address Type ' that is stored in another table called 'WeccoPartyAddress'?
I am trying to find duplicates for the first and last name, and mailing address where Address Type address = 'Mailing'
with dups as (
select
wp.GtId
from CORE.WeccoParty wp
where exists (select 1
from CORE.WeccoParty wpe
where wp.FirstName = wpe.FirstName
and wp.LastName = wpe.LastName
and wp.Dob = wpe.Dob
and wp.GtId <> wpe.GtId
)
)
select distinct
wp.GtId,
wp.CrmPartyId,
wp.LegalName,
wp.BusinessClass,
wp.RmFullName,
wp.PbeFullName,
wp.OverallClientStatus,
wp.OverallRpStatus,
wp.FirstName + ' ' + wp.LastName FullName,
wp.Dob
from CORE.WeccoParty wp
join dups d on d.GtId = wp.GtId
order by 9,1
Consider extending your CTE by adding a JOIN clause in outer and subquery to the WeccoPartyAddress table with needed WHERE clauses. Notice too the distinct added to avoid repeated IDs for possible one-to-many relationship between the tables.
with dups as (
select distinct p.GtId
from CORE.WeccoParty p
join CORE.WeccoPartyAddress a ON p.GtId = a.GtId
where exists (select 1
from CORE.WeccoParty sub_p
left join CORE.WeccoPartyAddress sub_a
on sub_p.GtId = sub_a.GtId and sub_a.AddressType = 'Mailing'
where (p.FirstName = sub_p.FirstName
and p.LastName = sub_p.LastName
and p.Dob = sub_p.Dob
and p.GtId <> sub_p.GtId)
and a.MailingAddress = sub_a.MailingAddress
and a.GtId <> sub_a.GtId
)
)
And depending on data and relationships (e.g., can GtId have same bio details AND/OR same mailing address?) which you would know more, you may need to adjust above query. These may involve swapping left join to join and/or the WHERE conditions such as:
where (p.FirstName = sub_p.FirstName
and p.LastName = sub_p.LastName
and p.Dob = sub_p.Dob
and p.GtId <> sub_p.GtId)
or
(a.MailingAddress = sub_a.MailingAddress
and a.GtId <> sub_a.GtId)

Not able to apply join in sql query

i want to add the join "JOIN {User}
ON {Deck}.[CreatedBy] = {User}.[Id]" in following query. I tried many combination but not succeeded. i want to fetch Name from User table
SELECT #CampaignQueryFilterString AS [Selected],
{Deck}.[Id], {Deck}.[Name],
{User}.[Name],
{Deck}.[TableOfContentId], {Deck}.[CreatedBy],
{Deck}.[LastModifiedOn], {Deck}.[ExpiryDate],s1.[Count]
FROM {Deck}
JOIN
(
SELECT {Deck}.[Id],
LISTAGG( {TagValue}.[Id], ',' ) WITHIN GROUP (ORDER BY {TagValue}.[TagCategoryId] ) AS Tags
FROM {Deck}
JOIN {AssociatedDeckTags}
ON {AssociatedDeckTags}.[DeckId] = {Deck}.[Id]
JOIN {TagValue}
ON {AssociatedDeckTags}.[TagValueId] = {TagValue}.[Id]
WHERE {Deck}.[IsPublished] = 1
AND {Deck}.[IsActive] = 1 AND {Deck}.[ReplacedByDeckId] IS NULL
AND {Deck}.[TableOfContentId] IN #TableOfContentIdFilterString
AND {Deck}.[ContentFileTypeId] IN #AllowedContentType
AND {Deck}.[ExpiryDate] > SYSDATE
GROUP BY {Deck}.[Id]
) DeckView
ON {Deck}.[Id] = DeckView.Id
JOIN(
SELECT COUNT(*) AS [Count], {DeckGroup}.[DeckId] AS [S1DeckId]
FROM {DeckGroup}
JOIN {Slide} ON {Slide}.[DeckGroupId] = {DeckGroup}.[Id]
GROUP BY {DeckGroup}.[DeckId]
) s1 ON s1.[S1DeckId] = {Deck}.[Id]
#RegexString
#SearchFilter
#CreatedBy
GROUP BY
{Deck}.[Id], {Deck}.[Name], {Deck}.[TableOfContentId],
{Deck}.[CreatedOn], {Deck}.[CreatedBy],
{Deck}.[LastModifiedOn], {Deck}.[ExpiryDate],
{Deck}.[NumOfPreviews], {Deck}.[NumOfDownloads],s1.[Count]
ORDER BY #Orderby
Looks like simply join, please try the below query (using your notation). I added left join and in group by clause - {User}.[Name]. Optionally you can use some aggregating function for {User}.[Name] - max(), listagg() and remove it from group by clause.
SELECT #CampaignQueryFilterString AS [Selected],
{Deck}.[Id], {Deck}.[Name], {User}.[Name], {Deck}.[TableOfContentId],
{Deck}.[CreatedBy], {Deck}.[LastModifiedOn], {Deck}.[ExpiryDate], s1.[Count]
FROM {Deck}
JOIN DeckView ON {Deck}.[Id] = DeckView.Id -- subquery1
JOIN s1 ON s1.[S1DeckId] = {Deck}.[Id] -- subquery2
LEFT JOIN {User} ON {Deck}.[CreatedBy] = {User}.[Id] -- <-- add join here
#RegexString
#SearchFilter
#CreatedBy
GROUP BY
{Deck}.[Id], {Deck}.[Name], {User}.[Name], -- <-- add column here
{Deck}.[TableOfContentId], {Deck}.[CreatedOn],
{Deck}.[CreatedBy], {Deck}.[LastModifiedOn],
{Deck}.[ExpiryDate], {Deck}.[NumOfPreviews],
{Deck}.[NumOfDownloads], s1.[Count]
ORDER BY #Orderby
You didn't show your tries, so we don't know if there was an error or undesired result. With this form of question that is all I can help. Also USER is one of Oracle Reserved Words, it's better to avoid using it as alias, variable name etc.

SQL Too few parameters when using WHERE clause and GROUP BY

I'm trying to write a query that will display a list of actors who star in at least 1 movie. I'm getting a "Too few parameters. Expected 2." error when I put the WHERE clause in. How do I fix this?
<cfquery name="qry1" datasource="torture">
SELECT
Actors.ActorID,
Actors.First_Name + ' ' + Actors.Last_Name AS Fullname,
COUNT( Title ) AS Titles
FROM
Actors
RIGHT JOIN Videos ON Actors.ActorID = Videos.ActorID
WHERE
Fullname <> NULL AND
Titles > 0
GROUP BY
Actors.ActorID,
Actors.First_name,
Actors.Last_Name;
</cfquery>
<cfform name="form" action="Page7Receiver.cfm">
<cfselect name="actor"
query="qry1"
value="ActorID"
display="FullName"
required="Yes"
multiple="No"
size="8">
</cfselect>
<br><input type="Submit" value="Submit">
</cfform>
The problem is caused by referencing names in your WHERE query that don't exist yet (Fullname and Titles).
Despite that SQL is in SELECT... FROM... WHERE... GROUP BY... HAVING... ORDER BY... order, in reality the SELECT is evaluated at the end, so your Fullname and Titles columns are not yet available in your WHERE clause.
I suggest reformulating the query like so:
SELECT
Actors.ActorId,
Actors.First_Name + ' ' + Actors.Last_Name AS FullName,
COALESCE( VideoInfo.VideoCount, 0 ) AS Titles
FROM
Actors
LEFT OUTER JOIN
(
SELECT
ActorId,
COUNT( * ) AS VideoCount
FROM
Videos
GROUP BY
ActorId
) AS VideoInfo ON Actors.ActorId = VideoInfo.ActorId
WHERE
COALESCE( VideoInfo.VideoCount, 0 ) > 0
AND
Actors.First_Name IS NOT NULL
AND
Actors.Last_Name IS NOT NULL
If we change it to an INNER JOIN then we can skip the Titles > 0 check because the nature of INNER JOIN means if an Actor has no Videos then there won't be a table-join on that ActorId anyway.
SELECT
Actors.ActorId,
Actors.First_Name + ' ' + Actors.Last_Name AS FullName,
VideoInfo.VideoCount AS Titles
FROM
Actors
INNER JOIN
(
SELECT
ActorId,
COUNT( * ) AS VideoCount
FROM
Videos
GROUP BY
ActorId
) AS VideoInfo ON Actors.ActorId = VideoInfo.ActorId
WHERE
Actors.First_Name IS NOT NULL
AND
Actors.Last_Name IS NOT NULL
Note, the <> NULL is not valid SQL. NULL is special: you have to use IS NOT NULL or IS NULL instead.

Grouping simiar records to one

I'm working on a social project and there are some tables which will have similar records which i'd like to group them into one. but with my query in brings all the records instead of grouping them into one.
SELECT
users_pics.email
, pic = MIN(pic)
, count(pic) AS total
,fname
,lname
,profile_pix
,RTRIM(wardrobe) as wardrobe
,gender
, resp_email
FROM
users_pics
INNER JOIN
profile
ON
users_pics.email = profile.email, dbo.viva_friends
WHERE
users_pics.stat = 'new'
AND
resp_email = MMColParam2
OR
req_email= MMColParam
AND
Status = 'Yes '
GROUP BY
users_pics.email
,fname,lname
,profile_pix
,wardrobe
,gender
,req_email
,resp_email
ORDER BY
MAX(users_pics.u_pic_id) DESC
please is there a way out. when i hit on the run button i get this.
Looks like you just want a simple GROUP BY;
SELECT users_pics.email, MIN(pic) AS pic, COUNT(pic) AS total, MAX(fname) AS fname,
MAX(lname) AS lname, MAX(profile_pix) AS profile_pic,
RTRIM(MAX(wardrobe)) AS wardrobe, MAX(gender) AS gender, MAX(resp_email) resp_email
FROM users_pics
INNER JOIN profile
ON users_pics.email = profile.email,
dbo.viva_friends
WHERE (users_pics.stat = 'new' AND resp_email = MMColParam2)
OR (req_email= MMColParam AND Status = 'Yes ')
GROUP BY
users_pics.email
Since I can't see your table structure, I can't tell what dbo.viva_friends is used for. It looks like it may be possible to just remove.