Join table and pick rows where for given id exists only one value - sql

I don't know, if I made good title, but please let me visualize this.
So I have two tables and for given case I need to select row where payment currency was ONLY in EUR.
Correct document Id's will be: 2, 3, 4, 5
These are overall bigger tables with 900k+ records.
Can you please suggest me how query should look?

use correlated subquery with not exists
select distinct a.document_id from tablename a inner join tablename b b on a.document_id=b.payment_docid
where not exists
(select 1 from tablename b1 where b1.payment_docid=b.payment_docid and currency<>'EUR')

Try this query:
select payment_docId from MyTable
group by payment_docId
having max(currency) = 'EUR'
and min(currency) = 'EUR'
or you could use having count(*) = 1 with min or max as well.

use corelated subquery
select t1.* from table2 as t1
where exists( select 1 from table2 t2 where t1.payment_docid=t2.payment_docid
having count(distinct currency)=1)
and currency='EUR'

It is possible to use INNER JOIN with the following conditions to get all rows:
SELECT
pd.payment_doc_id
, pd.currency
FROM DocTable dt
INNER JOIN PaymentDocs pd
ON dt.document_id = pd.payment_doc_id AND pd.currency IN ('EUR')
If you want distinct rows, then you can apply operator GROUP BY:
SELECT
pd.payment_doc_id
, pd.currency
FROM DocTable dt
INNER JOIN PaymentDocs pd
ON dt.document_id = pd.payment_doc_id AND pd.currency IN ('EUR')
GROUP BY pd.payment_doc_id
, pd.currency

Aggregation is the only efficient want :
select doc_id
from table t
group by doc_id
having min(currency) = max(currency) and min(currency) = 'EUR';

Related

SQL: Inner Join return one row based on criteria

This is probably simple, but i'm looking for the raw SQL to perform an INNER JOIN but only return one of the matches on the second table based on criteria.
Given two tables:
**TableOne**
ID Name
1 abc
2 def
**TableTwo**
ID Date
1 12/1/2014
1 12/2/2014
2 12/3/2014
2 12/4/2014
2 12/5/2014
I want to join but only return the latest date from the second table:
Expected Result:
1 abc 12/2/2014
2 def 12/5/2014
I can easily accomplish this in LINQ like so:
TableOne.Select(x=> new { x.ID, x.Name, Date = x.TableTwo.Max(y=>y.Date) });
So in other words, what does the above LINQ statement translate into in raw SQL?
There are two ways to do this:
Using GROUP BY and MAX():
SELECT one.ID,
one.Name,
MAX(two.Date)
FROM TableOne one
INNER JOIN TableTwo two on one.ID = two.ID
GROUP BY one.ID, one.Name
Using ROW_NUMBER() with a CTE:
; WITH cte AS (
SELECT one.ID,
one.Name,
two.Date,
ROW_NUMBER() OVER (PARTITION BY one.ID ORDER BY two.Date DESC) as rn
FROM TableOne one
INNER JOIN TableTwo two ON one.ID = two.ID
)
SELECT ID, Name, Date FROM cte WHERE rn = 1
You could join the first table with an aggregate query:
SELECT t1.id, d
FROM TableOne t1
JOIN (SELECT id, MAX[date] AS d
FROM TableTwo
GROUP BY id) t2 ON t1.id = t2.id
Something like:
SELECT TableOne.id, TableOne.name, MAX(TableTwo.Date)
FROM TableOne
LEFT JOIN TableTwo ON TableOne.id = TableTwo.id
GROUP BY TableOne.id, TableOne.name;
The join will produce a table with as many rows as TableTwo, but the group by will filter it to one row per TableOne's rows.
Since nobody else has covered a Common Table Expression (CTE) that will perform the task you want, I'll throw it in here:
with maxDates as (
select Id, max(Date)
from Table2
group by Id
)
select x.Id, x.Name, y.Date
from TableOne x
inner join maxDates y
on x.Id = y.id

selecting records from main table and count of each row in another table

I have 2 table in my database that tables are in relationship with foreign key
I want to select all records from main table and then select count of each row in another table than have same ID from main table I tried to create a select query but it is not work correctly
this query return all records from main table + count of all records from next table(not count of each row in relationship)
SELECT tblForumSubGroups_1.id, tblForumSubGroups_1.GroupID,
tblForumSubGroups_1.SubGroupTitle, tblForumSubGroups_1.SubGroupDesc,
(SELECT COUNT(dbo.tblForumPosts.id) AS Expr1
FROM dbo.tblForumSubGroups INNER JOIN dbo.tblForumPosts ON
dbo.tblForumSubGroups.id = dbo.tblForumPosts.SubGroupID) AS Expr1
FROM dbo.tblForumSubGroups AS tblForumSubGroups_1 INNER JOIN
dbo.tblForumPosts AS tblForumPosts_1 ON tblForumSubGroups_1.id
= tblForumPosts_1.SubGroupID
SELECT tblForumSubGroups_1.id, tblForumSubGroups_1.GroupID, tblForumSubGroups_1.SubGroupTitle, tblForumSubGroups_1.SubGroupDesc,
COUNT(tblForumPosts_1.id) AS Expr1
FROM dbo.tblForumSubGroups AS tblForumSubGroups_1
INNER JOIN dbo.tblForumPosts AS tblForumPosts_1 ON tblForumSubGroups_1.id = tblForumPosts_1.SubGroupID
GROUP BY tblForumSubGroups_1.id, tblForumSubGroups_1.GroupID, tblForumSubGroups_1.SubGroupTitle, tblForumSubGroups_1.SubGroupDesc
I would suggest cross apply as you can do a lot more things with it ...
SELECT t1.id,
t1.GroupID,
t1.SubGroupTitle,
t1.SubGroupDesc,
t2.val
FROM dbo.tblForumSubGroups AS t1
cross apply (SELECT COUNT(*)
FROM dbo.tblForumPosts as t2
WHERE t1.id = t2.SubGroupID) x(val)
Do not mix sub-query and join logic. Use only one of them. I prefer sub-select.
SELECT tblForumSubGroups_1.id,
tblForumSubGroups_1.GroupID,
tblForumSubGroups_1.SubGroupTitle,
tblForumSubGroups_1.SubGroupDesc,
(SELECT COUNT(*)
FROM dbo.tblForumPosts
WHERE dbo.tblForumSubGroups.id = dbo.tblForumPosts.SubGroupID) AS Expr1
FROM dbo.tblForumSubGroups AS tblForumSubGroups_1
Just to supply another answer though I believe the cross apply is likely the best option:
SELECT
A.id, A.GroupID, A.SubGroupTitle, A.SubGroupDesc,
B.IDCount AS Expr1
FROM dbo.tblForumSubGroups A
INNER JOIN (
Select SubGroupID, Count(ID) as IDCount
from dbo.tblForumPosts
Group By SubGroupID
) B On A.ID = B.SubGroupID

Join two tables and retrieve relevant data and calculate the result

We have two tables table1 and table2
Table 1
Table 2
We need the resultant table as :
All this should be done in a single SQL query
Thanks in advance.
I think you can make it without the second query, I tested it and returned your expected values.
select table_2.id_pro,
product_name,
SUM(1) as Quantity,
priceprod,
SUM(1) * priceprod as 'quantity * priceprod'
from Table_2
inner join Table_1 t1 on table_2.id_pro = t1.id_pro
group by table_2.id_pro, product_name, priceprod
And my SqlFiddle test http://sqlfiddle.com/#!3/08c2ef/1
I believe this should be what you need, or fairly close anyway! You need to group up your results from your first table to get your quantity value and then join those results to your second table to be able to create your desired output.
SELECT t1.id_pro,
t2.product_name,
s.Quantity,
t2.priceperprod,
s.Quantity * t2.priceperprod
FROM table_2 t2
INNER JOIN (
SELECT COUNT(*) AS Quantity,
t.id_pro
FROM table_1 t
GROUP BY t.id_pro
) t1 ON t2.id_pro = t1.id_pro
i believe that this is correct, i just JOIN the two tables AND used group by then count how many records each group, i hope this will help you, thanks.
SELECT
A.id_pro,
A.product_name,
(count(*)) AS Quantity,
A.priceperprod,
(COUNT(*) * A.priceperprod) AS Total
FROM table_2 A
LEFT JOIN table_1 B
ON B.id_pro = A.id_pro
GROUP BY A.id_pro
Guess this should be helpful to you.
SELECT A.PRODUCT_CODE, A.PRODUCT_NAME, B.QUANTITY,
A.PRICE PRICE_PER_PRODUCT,
(B.QUANTITY * A.PRICE) TOTAL_PRICE FROM
TABLE2 A,
(SELECT X.PRODUCT, COUNT(X.PRODUCT) QUANTITY FROM TABLE1 AS X
GROUP BY X.PRODUCT) as B
WHERE A.PRODUCT_CODE = B.PRODUCT
ORDER BY A.PRODUCT_CODE
Am doing following :
Taking the entire TABLE2 aliased as A
Getting the products and its corresponding count using group by and aliasing it as B
Selecting corresponding fields from table_Aliases A and B provided A's ProductCode and B's Products are same.

Getting count of records in child table using select statement

I have a stored procedure in which i am trying to select all the columns of a table Table 1. There is another table which uses Table1 primary key as foreign key. I want to count number of records in this foreign key table with that select like this:
SELECT *, count(*) VacancyCount
FROM Table1 hc
LEFT JOIN Table2 hv
on hc.CompanyID = hv.CompanyID
WHERE hc.Deleted = 0
group by hc.CompanyID
ORDER BY NameLang1
but it gives error:
Column 'dbo.Table1.NameLang1' is invalid in the select list because it
is not contained in either an aggregate function or the GROUP BY
clause.
Please suggest how to fix this?
Please try:
select
*,
(select COUNT(*) from Table2 hv where hv.CompanyID=hc.CompanyID) VacancyCount
from Table1 hc
where
hc.Deleted = 0
order by hc.NameLang1, VacancyCount desc
for ordering using the new column
select * from(
select
*,
CONVERT(NVARCHAR(100), (select COUNT(*) from Table2 hv where hv.CompanyID=hc.CompanyID)) VacancyCount
from Table1 hc
where
hc.Deleted = 0
)x
Order by CASE WHEN #OrderByParam = 1 THEN NameLang1 ELSE VacancyCount END
Provided column NameLang1 and VacancyCount are of same datatype.
You're doing grouping wrong. You need to use all the columns from Table 1 in SELECT instead of '*' and in GROUP BY clause as well.
Or you can try a different approach like this:
SELECT *
FROM Table1 hc
LEFT JOIN (SELECT CompanyID, COUNT(*) cnt FROM Table2 GROUP BY CompanyID) hv
on hc.CompanyID = hv.CompanyID
WHERE hc.Deleted = 0
ORDER BY NameLang1
You will have to list every column in the GROUP BY clause
These columns are those in the SELECT * bit.
This would be correct ANSI SQL anyway.
SELECT * itself is bad anyway: it is always better to explicitly list columns
Try in this way include column list in group by
SELECT column1,column2,column3..,NameLang1,count(*) VacancyCount
FROM Table1 hc
LEFT JOIN Table2 hv
on hc.CompanyID = hv.CompanyID
WHERE hc.Deleted = 0
group by column1,column2,column3
ORDER BY NameLang1

Select rows having dstinct values for two fields

Pardon me for the title. I have a table like this:
There will be thousands of rows and now I want to select the rows having the same group_id but vr_debit and vr_credit values must not be equal: ie;, in the image shown, none of the rows satisfy this criteria. If there is are two rows, say, (6,500.000,0) and(6,0,600.000), I want them as the result. Hope you get the idea.
Thank you.
Calculate each group using SUM() which is an aggregate function and filter them using HAVING clause.
SELECT GROUP_ID, SUM(vr_debit) totalDebit, SUM(vr_credit) totalCredit
FROM TableName
GROUP BY GROUP_ID
HAVING SUM(vr_debit) <> SUM(vr_credit)
if you want to get the uncalculated rows, you can join it on the subquery.
SELECT a.*
FROM TableName a
INNER JOIN
(
SELECT GROUP_ID
FROM TableName
GROUP BY GROUP_ID
HAVING SUM(vr_debit) <> SUM(vr_credit)
) b ON a.GROUP_ID = b.GROUP_ID
SQLFiddle Demo (for both queries)
Perhaps:
SELECT group_ID,
vr_debit,
vr_credit
FROM
dbo.TableName T1
WHERE
EXISTS(
SELECT 1 FROM dbo.TableName T2
WHERE T1.group_ID = T2.group_ID
AND T1.vr_debit <> T2.vr_debit
AND T1.vr_credit<> T2.vr_credit
AND T1.vr_debit <> T2.vr_credit
)
Also you can use this option
SELECT *
FROM dbo.test64 t
WHERE EXISTS (
SELECT 1
FROM dbo.test64 t2
WHERE t.group_id = t2.group_id
HAVING SUM(t2.vr_debit) - SUM(t2.vr_credit) != 0
)
Demo on SQLFiddle