Select how many documents are in other table for each person - sql

I have 3 tables.
Client,Documents and ClientDocuments.
The first one is the clients,where the information for each client are.
The second one is the documents, which document can go in the system.
The third one is the ClientDocuments, which client has which document.
Tables Here
I have to do a select where i get the information from the clients, and how many documents of the 3 types of the documents they have.
Example,Client 1 Have one document called 'Contrato Social',and 2 called 'Ata de Negociação'.
In the select must return every client and in the columns ContratoSocial returns 1,Ata Negociacao returns 2 and Aceite de Condições Gerais returns 0.
I did this to show.
select idFornecedor,
txtNomeResumido,
txtNomeCompleto,
--txtEmail,
--txtSenha,
bitHabilitado,
(SELECT Count(idDocumentosFornecedoresTitulo) FROM tbDocumentosFornecedores WHERE idDocumentosFornecedoresTitulo = 1) AS 'Contrato Social',
(SELECT Count(idDocumentosFornecedoresTitulo) FROM tbDocumentosFornecedores WHERE idDocumentosFornecedoresTitulo = 2) AS 'Ata de Negociação',
(SELECT Count(idDocumentosFornecedoresTitulo) FROM tbDocumentosFornecedores WHERE idDocumentosFornecedoresTitulo = 3) AS 'Aceite de Condições Gerais'
from dbo.tbFornecedores tbf
order by tbf.txtNomeResumido asc
returns this:
Returns of the query
But its just counting how many documents from that type is in the database, i want to filter for each client, how should i do?
Working answer:
select tbf.idFornecedor, tbf.txtNomeResumido, tbf.txtNomeCompleto,
tbf.bitHabilitado,
sum(case when idDocumentosFornecedoresTitulo = 1 then 1 else 0 end) as contrato_social,
sum(case when idDocumentosFornecedoresTitulo = 2 then 1 else 0 end) as Ata_de_Negociação,
sum(case when idDocumentosFornecedoresTitulo = 3 then 1 else 0 end) as Aceite_de_Condições_Gerais
from dbo.tbFornecedores tbf left join
tbDocumentosFornecedores df
on tbf.idFornecedor = df.idFornecedor
group by tbf.idFornecedor, tbf.txtNomeResumido, tbf.txtNomeCompleto, tbf.bitHabilitado
order by tbf.txtNomeResumido asc

You need some way of matching the rows in tbDocumentosFornecedores to the rows in tbFornecedores. Your question is not clear on what column is used for that, but I might guess something like idDocumentosFornecedore.
You could fix your query by using a correlation clause. However, I might instead suggest conditional aggregation:
select tbf.idFornecedor, tbf.txtNomeResumido, tbf.txtNomeCompleto,
tbf.bitHabilitado,
sum(case when idDocumentosFornecedoresTitulo = 1 then 1 else 0 end) as contrato_social,
sum(case when idDocumentosFornecedoresTitulo = 2 then 1 else 0 end) as Ata_de_Negociação,
sum(case when idDocumentosFornecedoresTitulo = 3 then 1 else 0 end) as Aceite_de_Condições_Gerais
from dbo.tbFornecedores tbf left join
tbDocumentosFornecedores df
on tbf.idDocumentosFornecedore = df.idDocumentosFornecedore -- this is a guess
group by tbf.idFornecedor, tbf.txtNomeResumido, tbf.txtNomeCompleto, tbf.bitHabilitado
order by tbf.txtNomeResumido asc

Related

Sum a column and perform more calculations on the result? [duplicate]

This question already has an answer here:
How to use an Alias in a Calculation for Another Field
(1 answer)
Closed 3 years ago.
In my query below I am counting occurrences in a table based on the Status column. I also want to perform calculations based on the counts I am returning. For example, let's say I want to add 100 to the Snoozed value... how do I do this? Below is what I thought would do it:
SELECT
pu.ID Id, pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END) AS Snoozed,
Snoozed + 100 AS Test
FROM
Prospects p
INNER JOIN
ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE
p.Store = '108'
GROUP BY
pu.Name, pu.Id
ORDER BY
Name
I get this error:
Invalid column name 'Snoozed'.
How can I take the value of the previous SUM statement, add 100 to it, and return it as another column? What I was aiming for is an additional column labeled Test that has the Snooze count + 100.
You can't use one column to create another column in the same way that you are attempting. You have 2 options:
Do the full calculation (as #forpas has mentioned in the comments above)
Use a temp table or table variable to store the data, this way you can get the first 5 columns, and then you can add the last column or you can select from the temp table and do the last column calculations from there.
You can not use an alias as a column reference in the same query. The correct script is:
SELECT
pu.ID Id, pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END)+100 AS Snoozed
FROM
Prospects p
INNER JOIN
ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE
p.Store = '108'
GROUP BY
pu.Name, pu.Id
ORDER BY
Name
MSSQL does not allow you to reference fields (or aliases) in the SELECT statement from within the same SELECT statement.
To work around this:
Use a CTE. Define the columns you want to select from in the CTE, and then select from them outside the CTE.
;WITH OurCte AS (
SELECT
5 + 5 - 3 AS OurInitialValue
)
SELECT
OurInitialValue / 2 AS OurFinalValue
FROM OurCte
Use a temp table. This is very similar in functionality to using a CTE, however, it does have different performance implications.
SELECT
5 + 5 - 3 AS OurInitialValue
INTO #OurTempTable
SELECT
OurInitialValue / 2 AS OurFinalValue
FROM #OurTempTable
Use a subquery. This tends to be more difficult to read than the above. I'm not certain what the advantage is to this - maybe someone in the comments can enlighten me.
SELECT
5 + 5 - 3 AS OurInitialValue
FROM (
SELECT
OurInitialValue / 2 AS OurFinalValue
) OurSubquery
Embed your calculations. opinion warning This is really sloppy, and not a great approach as you end up having to duplicate code, and can easily throw columns out-of-sync if you update the calculation in one location and not the other.
SELECT
5 + 5 - 3 AS OurInitialValue
, (5 + 5 - 3) / 2 AS OurFinalValue
You can't use a column alias in the same select. The column alias do not precedence / sequence; they are all created after the eval of the select result, just before group by and order by.
You must repeat code :
SELECT
pu.ID Id,pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END) AS Snoozed,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END)+ 100 AS Test
FROM
Prospects p
INNER JOIN
ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE
p.Store = '108'
GROUP BY
pu.Name, pu.Id
ORDER BY
Name
If you don't want to repeat the code, use a subquery
SELECT
ID, Name, LeadCount, Working, Uninterested,Converted, Snoozed, Snoozed +100 AS test
FROM
(SELECT
pu.ID Id,pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END) AS Snoozed
FROM Prospects p
INNER JOIN ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE p.Store = '108'
GROUP BY pu.Name, pu.Id) t
ORDER BY Name
or a view

Trying to get count of votes in SQL based on ID

Table structures:
Solution_Votes:
ID int
SolutionID string
Vote int
Solution:
ID int
Solution
VotesUp
VotesDown
Code:
SELECT
*,
(SELECT SUM(CASE WHEN voteUp = 1 THEN 1 ELSE 0 END)
FROM Solutions_Votes) AS VoteCountUp,
(SELECT SUM(CASE WHEN voteDown = 0 THEN 1 ELSE 0 END)
FROM Solutions_Votes) AS VoteCountDown
FROM
Solution
When I run this query it gives me the count on each row for voteUpCount and voteDownCount. I need the count to be based on the solution ID so that each solution has its count of up votes and down votes. If anybody can help it would be appreciated. Thanks in advance!
Just use conditional aggregation. In your case this is simple:
select sv.solutionid,
sum(case when sv.voteUp = 1 then 1 else 0 end) as VoteCountUp,
sum(case when sv.voteDown = 0 then 1 else 0 end) as VoteCountDown
from solutions_votes sv
group by sv.solutionid;
You only need the solutions table if some solutions have no votes and you want to include them.
EDIT:
You would include solutions in various way. Here is one:
select s.*, ss.VoteCountUp, ss.VoteCountDown
from solutions s left join
(select sv.solutionid,
sum(case when sv.voteUp = 1 then 1 else 0 end) as VoteCountUp,
sum(case when sv.voteDown = 0 then 1 else 0 end) as VoteCountDown
from solutions_votes sv
group by sv.solutionid
) ss
on s.solutionid = ss.solutionid;

Wrong data on SQL query

My requirement is to fetch details from two tables REPORT_API_USAGE & REPORT_API_PAGES. I need to get TERMNAME, COUNT(TERMNAME) from REPORT_API_USAGE and COUNT(CTYPE) for both event and download from REPORT_API_PAGES. Both table has common field termid. The requirement is to get TERMNAME, COUNT(TERMNAME) with related events and file-download.
There is only one TERMID 24 in REPORT_API_PAGES With CTYPE as download. So the result should be Face-to-Face Learning 1 0 1
I have a page Face-to-Face Learning with TERMID'24. I have added an event and document with reference ofFace-to-Face Learning. Once i viewedFace-to-Face Learningpage,COUNT(TERMNAME)will store the page hit value inREPORT_API_USAGEtable. Once the event and document pages are viewed,REPORT_API_USAGEwill store the details withTERMIDreference. I need to create a report of views. Need to getFace-to-Face Learning` view count with related event and document hits.
You have two rows with termname='Face-to-Face Learning' in table report_api_usage therefore returned two lines.
You should use:
select ap.termname,
count(distinct ap.termname) as tot,
count(distinct ai.ctype) as event,
sum(case when ai.ctype = 'event' then 1 else 0 end) as page
from ...
I don't understand what you want count.. If you want count how many repoet_api_pages have ctype 'event' or 'download' use follows query:
select ap.termname,
count(ap.termname) as tot, -- if it total count rows in table report_api_usage, if you need unique count use distinct inside count function
sum(case when ai.ctype = 'download' then 1 else 0 end) as page_download
sum(case when ai.ctype = 'event' then 1 else 0 end) as page_event
from ...
Finlay i found the expensive query.
SELECT AIP.TERMID,
(select count(RAU.TERMNAME) FROM REPORT_API_USAGE RAU WHERE RAU.TERMID = AIP.TERMID AND RAU.VOCID = 4) as page_views,
(select sum(count(RAU.TERMNAME)) FROM REPORT_API_USAGE RAU WHERE RAU.VOCID = 4
and RAU.TERMID in (select AIP.TERMID from REPORT_API_PAGES AIP GROUP BY AIP.TERMID) group by RAU.VOCID) as page_views_sum,
(select sum(count(AIP2.TERMID)) from REPORT_API_PAGES AIP2 join REPORT_API_USAGE RAU ON (RAU.TERMID = AIP2.TERMID AND RAU.VOCID = 4) where aip2.ctype = 'download' GROUP by AIP2.termid) as download_sum,
(select sum(count(AIP2.TERMID)) from REPORT_API_PAGES AIP2 join REPORT_API_USAGE RAU ON (RAU.TERMID = AIP2.TERMID AND RAU.VOCID = 4) where aip2.ctype = 'event' GROUP by AIP2.termid) as event_sum,
COUNT(case when aip.ctype = 'download' then 1 else null end) as page_download,
COUNT(case when aip.ctype = 'event' then 1 else null end) as page_event
from REPORT_API_PAGES AIP
GROUP BY AIP.TERMID

nested SQL queries on one table

I am having trouble formulating a query to get the desired output.
This query involves one table and two columns.
First column bld_stat has 4 different values Private, public, Public-Abandoned, Private-Abandoned the other column bld_type, single_flr, multi_flr, trailer, Whs.
I need to get results that look like this:
So far I can get the first two columns but after that I have not been able to logically get a query to work
SELECT bld_stat, COUNT(grade) AS single_flr
FROM (SELECT bld_stat,bld_type
FROM bld_inventory WHERE bld_type = 'single_flr') AS grade
GROUP BY bld_stat,bld_type,grade
The term you are going for is pivoting. I think this should work...no need for the subquery, and I've changed your group by to only bld_stat
SELECT bld_stat,
sum(case when bld_type = 'singl_flr' then 1 else 0 end) AS single_flr,
sum(case when bld_type = 'multi_flr' then 1 else 0 end) AS multi_flr,
sum(case when bld_type = 'trailer' then 1 else 0 end) AS trailer,
sum(case when bld_type = 'whs' then 1 else 0 end) AS WHS
FROM bld_inventory
GROUP BY bld_stat

SQL Count with multiple conditions then join

Quick one,
I have a table, with the following structure
id lid taken
1 1 0
1 1 0
1 1 1
1 1 1
1 2 1
Pretty simply so far right?
I need to query the taken/available from the lid of 1, which should return
taken available
2 2
I know I can simply do two counts and join them, but is there a more proficient way of doing this rather than two separate queries?
I was looking at the following type of format, but I can not for the life of me get it executed in SQL...
SELECT
COUNT(case taken=1) AS taken,
COUNT(case taken=0) AS available FROM table
WHERE
lid=1
Thank you SO much.
You can do this:
SELECT taken, COUNT(*) AS count
FROM table
WHERE lid = 1
GROUP BY taken
This will return two rows:
taken count
0 2
1 2
Each count corresponds to how many times that particular taken value was seen.
Your query is correct just needs juggling a bit:
SELECT
SUM(case taken WHEN 1 THEN 1 ELSE 0 END) AS taken,
SUM(case taken WHEN 1 THEN 0 ELSE 1 END) AS available FROM table
WHERE
lid=1
Alternatively you could do:
SELECT
SUM(taken) AS taken,
COUNT(id) - SUM(taken) AS available
FROM table
WHERE
lid=1
SELECT
SUM(case WHEN taken=1 THEN 1 ELSE 0 END) AS taken,
SUM(case WHEN taken=0 THEN 1 ELSE 0 END) AS available
FROM table
WHERE lid=1
Weird application of CTE's:
WITH lid AS (
SELECT DISTINCT lid FROM taken
)
, tak AS (
SELECT lid,taken , COUNT(*) AS cnt
FROM taken t0
GROUP BY lid,taken
)
SELECT l.lid
, COALESCE(a0.cnt, 0) AS available
, COALESCE(a1.cnt, 0) AS taken
FROM lid l
LEFT JOIN tak a0 ON a0.lid=l.lid AND a0.taken = 0
LEFT JOIN tak a1 ON a1.lid=l.lid AND a1.taken = 1
WHERE l.lid=1
;