How do I display different values as different columns in SQL? - sql

I have a table with columns UserID, SiteID, SiteViews and another with UserID, First, Last
And I need to display the data as First + Last, Site1Views, Site2Views
There are only 2 site IDs and I need to have the sum of the SiteViews per User.
Currently I have:
select s.UserFirstName + ' ' + s.UserLastName as 'Name',
j1.SiteViews as 'Site1Name',
j2.SiteViews as 'Site2Name'
from (Users s INNER JOIN Usage j on s.UserID = j.UserID)
I don't know how to do this. Any help would be appreciated.

Sounds like you might want to use PIVOT for this? I can't test it, but this should get you going int he right direction?
select s.UserFirstName + ' ' + s.UserLastName as Name,
[Site1Name],
[Site2Name]
FROM
(SELECT s.UserFirstName + ' ' + s.UserLastName,
SiteName,
SiteVisits
from Users s
INNER JOIN Usage j1
on s.UserID = j1.UserID
)
PIVOT (SUM(SiteVisits) FOR SiteName IN ([Site1Name],[Site2Name])) as p

how I understood it
select s.UserFirstName + ' ' + s.UserLastName as Name
,(Select COUNT(*) from SiteViews s1 where s.UserID = s1.UserID /*other condition*/) as SiteView1
,(Select COUNT(*) from SiteViews s2 where s.UserID = s2.UserID /*other condition*/) as SiteView2
from Users s

Related

SQL get to select multiple names from select subquery

I am writing select statement in SQL Server. I have to add a select query.
select
acct.AccountID,
acct.Username,
acct.LastNm + ', ' + acct.FirstNm as Name ,
acct.Lastlogin,
acct.email as Email,
(select acct2.FirstNm + ' ' + acct2.LastNm as Name from tblUserAccount acct2
join tblReviewers ra2 on acct2.AccountID = ra2.ReviwerID) as Reviewers
from tblUserAccount acct
I need to get more names from a table called tblReviwers. So 1 user from the tblUserAccount table could be associated with multiple reviews.
The tblReviewers only has 3 column AnalystID, ReviewerID, and Date. When I select on the JOIN between TblUserAccount and TblReviewers on a test AccountID = AnalystID, I can get multiple ReviewerIDs, which their firstname and lastname are located in the tblUserAccount. This is the reason why I use a select subquery
When I run the query, I get the following error
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
I am trying to write a VIEW to get a data.
Any help is greatly appreciated.
A query for a column name can only contain a single record result set. If you have an entry with multiple results causes that error.
I think you are missing disclosure of a possible extra component needed in the reviewers table, the who entered it. This will result in a query similar to the following.
The aliases and relations will appear obvious, but need to be confirmed for your actual structure.
select
EnterBy.AccountID,
EnterBy.Username,
EnterBy.LastNm + ', ' + EnterBy.FirstNm as Name ,
EnterBy.Lastlogin,
EnterBy.email as Email,
ReviewBy.FirstNm + ' ' + ReviewBy.LastNm as ReviewerName
from
tblReviewers r
tblUserAccount EnterBy
on r.AccountID = EnterBy.AccountID
tblUserAccount ReviewBy
on r.ReviwerID = ReviewBy.AccountID
REVISION BASED ON ADDITIONAL DATA
Based on providing the analystID on who entered, you should be good with
select
EnterBy.AccountID,
EnterBy.Username,
EnterBy.LastNm + ', ' + EnterBy.FirstNm as Name ,
EnterBy.Lastlogin,
EnterBy.email as Email,
STUFF(( Select
', [' + ReviewBy.LastNm + ', ' + ReviewBy.FirstNm + '] ' AS [text()]
From
tblReviewers r
JOIN tblUserAccount ReviewBy
on r.ReviwerID = ReviewBy.AccountID
where
r.AnaylstID = EnterBy.AccountID
For XML PATH('')), 1, 2, '' ) as AllReviewers
from
tblUserAccount EnterBy
You cannot have a column that contains multiple rows in a single result set, it just doesn't make sense from SQL perspective. Hence the error.
You should JOIN the tblReviewers table instead of subselecting it. That will yield all Reviewers. Then, JOIN again on the tblUserAccount table to get the name of the Reviewer, and you are all set.
SELECT
acct.AccountID,
acct.Username,
acct.LastNm + ', ' + acct.FirstNm as Name ,
acct.Lastlogin,
acct.email as Email,
acct2.LastNm + ', ' + acct2.FirstNm as ReviewerName ,
FROM tblUserAccount acct
JOIN tblReviewers revi
ON on acct.AccountID = revi.ReviewerID
JOIN tblUserAccount acct2
ON on acct2.AccountID = revi.AnalystID
Starting from Sql Server 2017, You can use something like STRING_AGG function, which combines values from multiple rows into a single string.
Then, your Reviewers column in your query might look like this:
(select STRING_AGG(Name, ',') from
(select acct2.FirstNm + ' ' + acct2.LastNm as Name from tblUserAccount acct2
join tblReviewers ra2 on acct2.AccountID = ra2.ReviwerID
where ra2.AnalystID = acct.AccountID)
) as Reviewers
In this case, names(first name + last name) of the reviewers for the current user will be separated by commas.
Subselects in select lists can only be used to return one value.
In your case, use joins
SELECT
a.AccountID,
a.Username,
a.LastNm + ', ' + a.FirstNm as Name ,
a.Lastlogin,
a.email as Email,
b.LastNm + ', ' + b.FirstNm as ReviewerName
FROM
tblUserAccount a
LEFT JOIN tblReviewers r ON a.AccountID = r.AnalystID
INNER JOIN tblUserAccount b ON r.ReviewerID = b.AccountID
I also used a LEFT JOIN to the reviewers table, in case there is no reviewer defined for an analyst.
You will get several rows per analyst, if more than one reviewer is assigned to it. Usually I solve this problem in the front-end by making a report that puts the main data in a group header (the analyst) and the related date (the reviewers) in the detail section of the report.
Starting with SQL Server 2017, you can also use the STRING_AGG function to concatenate the values of string expressions.
SELECT
a.AccountID,
a.Username,
a.LastNm + ', ' + a.FirstNm AS Name ,
a.Lastlogin,
a.email AS Email,
STRING_AGG(
( SELECT b.LastNm + ' ' + b.FirstNm
FROM
tblReviewers
INNER JOIN tblUserAccount b ON r.ReviewerID = b.AccountID
WHERE
r.AnalystID = a.AccountID ),
', ') AS ReviewerName
FROM
tblUserAccount a
This allows you to return more than one reviewer in one field.

Using the results of a SQL query as parameters for a second one

Our SQL developer put together the following query to basically pull a list of any employee who has logged into our system today. This query works perfectly and will spit out a list of names. What I need to do is take the list of names it spits out and then use those in a new query to change a column on a different table for each of those names.
select distinct(t.CC_FullName) as Employee,
t.CC_Supervisor as Supervisor,
t.StaffCimID
from (
select s.*,
r.CC_FullName,
r.CC_Supervisor,
r.StaffCimID
from (
select AgentFirstName + ' ' + AgentLastName as AgentName,
Agent
from pia.dbo.Five9IntraDayExtract with(nolock)
group by AgentFirstName + ' ' + AgentLastName,
Agent
) s
inner join pia.dbo.StaffInformationNew r with(nolock)
ON CASE
WHEN s.Agent LIKE '%_manual' AND s.Agent = r.Five9Name_MTM THEN 1
WHEN s.Agent NOT LIKE '%_manual' AND s.Agent = r.Five9Name THEN 1
ELSE 0
END = 1
and r.EndDate is null
) t
where t.CC_FullName is not null
and t.StaffCimID is not null
order by t.CC_FullName, t.CC_Supervisor
so basically after that runs I get a list with three columns. I need to take the name column and basically do the following:
Update Attendance Set Seated = '1' where name = 'John Doe'
I need to do that for every result from the initial query. What's the best way to do that?
Add that to the top of your query...
Update Attendance
Set Seated = '1'
where name in
(select t.CC_FullName from (
select s.*,
r.CC_FullName,
r.CC_Supervisor,
r.StaffCimID
from (
select AgentFirstName + ' ' + AgentLastName as AgentName,
Agent
from pia.dbo.Five9IntraDayExtract with(nolock)
group by AgentFirstName + ' ' + AgentLastName,
Agent
) s
inner join pia.dbo.StaffInformationNew r with(nolock)
ON CASE
WHEN s.Agent LIKE '%_manual' AND s.Agent = r.Five9Name_MTM THEN 1
WHEN s.Agent NOT LIKE '%_manual' AND s.Agent = r.Five9Name THEN 1
ELSE 0
END = 1
and r.EndDate is null
) t
where t.CC_FullName is not null
and t.StaffCimID is not null)

SQL show the max of count

I am using SQL server 2014. I have two tables Member and MemberPosition. The MemberPostion table records a history of each member in the database. The memberID is the primary key in the member table, and is a foreign key in the MemberPosition table. I need to return the member that has held the most positions.
Here is the query I am using:
Select
M.MemberFName + ' ' + M.MemberLName as Name
from Member M
Join MemberPosition MP
ON MP.MemberID = M.MemberID
Group By M.MemberFName + ' ' + M.MemberLName
Having Count(MP.MemberID) = (Select max(P) from
(Select Count(MP.MemberID) as P From MP))
I am getting an error near the last )
It tells me incorrect syntax near 'End of file'. Expecting AS,ID, or QUOTED_ID.
Can you tell me what I am doing wrong. I have tried following other examples from the forums but I cannot figure this out.
Subqueries in the from clause need an alias. In your case, this is buried deep in the having clause:
Select M.MemberFName + ' ' + M.MemberLName as Name
from Member M Join
MemberPosition MP
ON MP.MemberID = M.MemberID
Group By M.MemberFName + ' ' + M.MemberLName
Having Count(MP.MemberID) = (Select max(P)
from (Select Count(MP.MemberID) as P
From MP
) p
------------------------------------^
);
There are other ways to do what you want but this follows your query.
Here is an alternative:
Select TOP 1 WITH TIES M.MemberFName + ' ' + M.MemberLName as Name
from Member M Join
MemberPosition MP
ON MP.MemberID = M.MemberID
Group By M.MemberFName + ' ' + M.MemberLName
ORDER BY COUNT(*) DESC;

SQL Pivot on Foreign Key but display different column header

I had written a stored procedure that would first get a list of columns which were distinct account descriptions and use those to pivot on for getting daily monetary values per account. The problem I encountered is the end user has instances where they have the same Account description for multiple accounts so I am now using AccountID's to pivot on.
Below you will find my query to get Distinct Account ID's and then to create the pivot table. My end goal is that the current column headers for the user are useless i.e. "1504" "1505" "1683" etc. These have no meaning to them. How can I either rename column headers of a result set or somehow use a pivot based on distinct account ID's while displaying a description instead. GLAccounts.Description is the column with the description I would like to display instead of the GLAccounts.AccountID.
SELECT #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(AccountID)
FROM (
SELECT DISTINCT GLAccounts.AccountID AS AccountID
FROM GeneralLedger
INNER JOIN DailyFiles ON GeneralLedger.DailyFileID = DailyFiles.DailyFileID
Inner Join GLAccounts ON GeneralLedger.AccountID = GLAccounts.AccountID
-- Get All Daily Files for company and date range
INNER JOIN
(SELECT DailyFileID
FROM DailyFiles
WHERE (DailyFiles.DailyFileDate >= CONVERT(DATETIME, #MTDStart, 102)) AND (DailyFiles.DailyFileDate <= CONVERT(DATETIME, #MTDEnd, 102))
AND CompanyID = #CompanyID) AS DAILYFILEIDS ON GeneralLedger.DailyFileID = DAILYFILEIDS.DailyFileID
) x
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query = N'SELECT A.*
from(
SELECT SummedAccounts.Date, SUM(SummedAccounts.DayTotal) AS DayTotal, SummedAccounts.AccountID AS AccountID
FROM(SELECT DailyFiles.DailyFileDate AS Date, IIF(GLAccounts.FriendlyName IS NOT NULL AND GLAccounts.FriendlyName <> '''', GLAccounts.FriendlyName, GLAccounts.Description) as AccountDescription, IIF(GeneralLedger.SavedToCredit = 1,
--Saved To Credit Is True
IIF(AccountTYpes.PositiveToCredit = 1, (SUM(GeneralLedger.Credit + GeneralLedger.Debit)), (SUM(GeneralLedger.Credit + GeneralLedger.Debit) * -1)),
--Saved To Credit Is False
IIF(AccountTYpes.PositiveToCredit = 1, ( SUM(GeneralLedger.Credit + GeneralLedger.Debit) * -1), (SUM(GeneralLedger.Credit + GeneralLedger.Debit)))) AS DayTotal, GeneralLedger.SavedToCredit, AccountTypes.PositiveToCredit, GeneralLedger.AccountID AS AccountID
FROM GeneralLedger
INNER JOIN DailyFiles ON GeneralLedger.DailyFileID = DailyFiles.DailyFileID
Inner Join GLAccounts ON GeneralLedger.AccountID = GLAccounts.AccountID
INNER JOIN AccountTypes ON AccountTypes.AccountTypeID = GLAccounts.AccountTypeID
-- Get All Daily Files for company and date range
INNER JOIN
(SELECT DailyFileID
FROM DailyFiles
WHERE (DailyFiles.DailyFileDate >= #MTDStart) AND (DailyFiles.DailyFileDate <= #MTDEnd)
AND CompanyID = #CompanyID) AS DAILYFILEIDS ON GeneralLedger.DailyFileID = DAILYFILEIDS.DailyFileID
GROUP BY GeneralLedger.AccountID, DailyFiles.DailyFileDate, GLAccounts.FriendlyName, GLAccounts.Description, GeneralLedger.SavedToCredit, AccountTypes.PositiveToCredit) SummedAccounts
GROUP BY SummedAccounts.Date, SummedAccounts.AccountID
) y
pivot
(
min(DayTotal)
for AccountID in (' + #cols + ')
) A'
Result Sets Look Like:

Sql Inner Join Dont Have Result

First of all thanks a lot all replys and comments. I want to listed some fields from 4 tables. My question is if ODEMELER(Customer Payments) tables is dont have BORCLAR(Customers Debt) tables value. Namely;
MusteriID is = 1.
This Customer buy a item. I insert this process to BORCLAR table(BorcMusteriID=1) but ODEMELER table is null for this customer and OdemeMusteriID=!!! (null) because customer is not payment. And i want to list all of debts from all customers this code;
(SELECT SUM(BORCLAR.BorcTutari) FROM BORCLAR WHERE BORCLAR.BorcMusteriID=
ODEMELER.OdemeMusteriID)-
(SELECT SUM(ODEMELER.OdemeTutar) FROM ODEMELER where BORCLAR.BorcMusteriID=
ODEMELER.OdemeMusteriID))
AS [Borç Toplamı] FROM BORCLAR)
but this code is reply me only have BorcMusteriID,OdemeMusteriID valid records then my a lot of customers buy items but dont payment now. I dont list this. I try this code but it is wrong;
((SELECT SUM(BORCLAR.BorcTutari) FROM BORCLAR WHERE
BORCLAR.BorcMusteriID=ODEMELER.OdemeMusteriID)-
(SELECT SUM(ODEMELER.OdemeTutar) FROM ODEMELER where
BORCLAR.BorcMusteriID=
CASE (SELECT COUNT(*) FROM ODEMELER WHERE
ODEMELER.OdemeMusteriID=BORCLAR.BorcMusteriID)
WHEN 0 THEN ODEMELER.OdemeMusteriID = ODEMELER.OdemeMusteriID
ELSE ODEMELER.OdemeMusteriID=0 END)) AS [Borç Toplamı] FROM BORCLAR
Complete of my code;
set dateformat dmy
SELECT
(SELECT TOP 1 BORCLAR.BorcTarih FROM BORCLAR WHERE BORCLAR.BorcTarih <=
CONVERT(DATETIME, GETDATE(), 104)
and
BORCLAR.BorcMusteriID=MUSTERILER.MusteriID order by BORCLAR.BorcTarih desc)
as [TARİH],
MUSTERILER.Unvan,MUSTERILER.Ad + ' ' + MUSTERILER.Soyad AS [Adı Soyadı],
MUSTERILER.Mahalle +
' ' + MUSTERILER.Cadde + ' '+MUSTERILER.Sokak + ' ' + MUSTERILER.ApartmanAdi+
' NO:' +
MUSTERILER.Numara + ' KAT:' + MUSTERILER.Kat + ' DAİRE:'+
MUSTERILER.Daire AS [Adres],
ARACSUBETANIMLAR.AracSubeAdi as [Araç/Şube Adı],
((SELECT SUM(BORCLAR.BorcTutari) FROM BORCLAR WHERE BORCLAR.BorcMusteriID=
ODEMELER.OdemeMusteriID)-
(SELECT SUM(ODEMELER.OdemeTutar) FROM ODEMELER where BORCLAR.BorcMusteriID=
ODEMELER.OdemeMusteriID))
AS [Borç Toplamı] FROM BORCLAR
INNER JOIN ARACSUBETANIMLAR ON BORCLAR.BorcAracSube = ARACSUBETANIMLAR.AracSubeID
INNER JOIN ODEMELER ON BORCLAR.BorcMusteriID = ODEMELER.OdemeMusteriID
INNER JOIN MUSTERILER ON BORCLAR.BorcMusteriID = MUSTERILER.MusteriID
where
BORCLAR.BorcAracSube=ARACSUBETANIMLAR.AracSubeID
and
((SELECT SUM(BORCLAR.BorcTutari) FROM BORCLAR WHERE BORCLAR.BorcMusteriID=
ODEMELER.OdemeMusteriID)-
(SELECT SUM(ODEMELER.OdemeTutar) FROM ODEMELER where BORCLAR.BorcMusteriID=
ODEMELER.OdemeMusteriID)>0)
group by MUSTERILER.Unvan,MUSTERILER.Soyad,MUSTERILER.Ad,
ARACSUBETANIMLAR.AracSubeAdi,
ODEMELER.OdemeMusteriID,BORCLAR.BorcMusteriID,MUSTERILER.
Cadde,MUSTERILER.Daire,
MUSTERILER.ApartmanAdi,MUSTERILER.Mahalle,MUSTERILER.Kat,
MUSTERILER.Numara,MUSTERILER.Sokak,
MUSTERILER.MusteriID
Thanks a lot.
Looks like you want all customer balances regardless whether they have paid anything or not. You have purchases in one table (BORCLAR) and payments in the other table (ODEMELER). I am not sure what language you are speaking, but I guess "MusteriID" is the customer ID. You can use CTEs to get total purchases and payments by customer first and then join on that. Something like this:
;WITH BorclarTotal AS (
SELECT BORCLAR.BorcMusteriID, SUM(BORCLAR.BorcTutari) AS BorcTutari
FROM BORCLAR
GROUP BY BORCLAR.BorcMusteriID
), OdemelerTotal AS (
SELECT ODEMELER.OdemeMusteriID, SUM(ODEMELER.OdemeTutar) AS OdemeTutar
FROM ODEMELER
GROUP BY ODEMELER.OdemeMusteriID
)
SELECT bt.BorcMusteriID, bt.BorcTutari - ISNULL(ot.OdemeTutar, 0)
FROM BorclarTotal bt
LEFT JOIN OdemelerTotal ot ON bt.BorcMusteriID = ot.OdemeMusteriID
WHERE bt.BorcTutari != ISNULL(ot.OdemeTutar, 0);