i need to write one efficient query on the 2 tables below, with the conditions follow the tables:
First Table
CityCode CustomerID AccountID
Paris 1 1
Roma 2 1
London 1 2
Paris 3 2
Roma 4 3
Berlin 5 4
Second Table
Credit_card_ind Credit AccountID
0 1000 1
1 5000 2
0 2300 3
1 30000 4
0 - doesn't have card
1 - has a card
In the query we need the following conditions:
1. all customers which their credit is above 5000
2. not showing accounts where one of their customers doesn't have credit card
3. all the accounts where their credit is below 30000
4. not showing accounts where one of their customers is from 'Roma'
5. showing accounts with more than 1 customers.
(*) - there might be no records return.
i wrote the query as follow and i wanted to confirm its the best way to do so, where the intention is to reduce the number of times we approach the tables and doing Joins:
Select c.AccountID,
c.CustomerID
From Customers as c
Join credit_cards as ca on c.AccountID = ca.AccountID
Where ca.credit > 5000 And ca.credit < 30000
And c.AccountID not in (
Select Distinct newTBL.AccountID
From (
Select c1.CustomerID,
c1.AccountID
From customers as c1
Join credit_cards as ca1 on c.AccountID = ca.AccountID
Where ca1.credit_card_ind = 0
Or c1.CityCode like ‘Roma’
) as newTBL
)
And c.AccountID in (
Select newCus.AccountID
From (
Select AccountID,
Count(CustomerID) as [Num_of_Cus]
From customers
Group by AccountID
) as newCus
Where newCus.[Num_of_Cus] > 1
)
First, you can simplify your query by removing the nested subqueries:
Select c.AccountID, c.CustomerID
From Customers c Join
credit_cards ca
on c.AccountID = ca.AccountID
Where ca.credit > 5000 And ca.credit < 30000 And
c.AccountID not in (Select c1.CustomerID
From customers c1 Join
credit_cards ca1
on c.AccountID = ca.AccountID
Where ca1.credit_card_ind = 0 Or c1.CityCode like 'Roma'
) And
c.AccountID in (Select AccountID
From customers
Group by AccountID
Having Count(CustomerID) > 1
);
This may help. You can also write this using window functions, which are probably more efficient. I think the following query captures your original conditions:
select c.AccountID, c.CustomerID
from (select c.*, count(*) over (partition by c.accountid) as cnt,
max(case when c.CityCode like 'Roma' then 1 else 0 end) as cnt_Roma
from customers c
) c join
credit cr
on c.accountid = cr.accountid
where ca.credit > 5000 And ca.credit < 30000 and
c.cnt > 0 and c.cnt_Roma = 0 and
ca.credit_card_ind <> 0;
Try this.
SELECT cs.AccountID
FROM customer cs
JOIN credit cr
ON cs.AccountID = cr.AccountID
WHERE CityCode <> 'Roma'
AND Credit_card_ind = 1
AND Credit > 5000
AND Credit < 30000
GROUP BY cs.AccountID
HAVING Count(cs.CustomerID) > 1
Related
I have a table of bank transactions, AccountTransaction, and rows with for e.g.
Amount
Payee_Name
Transaction_ID
Is_Corresponding_Transaction
69.00
Bob Jones
1
1
-69.00
Bob Jones
1
0
25.00
Bill
2
1
-25.00
Bill
2
0
297.00
Sally
3
1
-5.00
Ted
4
1
2.50
Ted
4
0
2.50
Ted
4
0
How do I select only (all) TS like Sally's where the Transaction ID only occurs once?
Bonus points: How do I select TS like Ted's where the sum of all Is_Corresponding_Transaction = 0 != the sum of Is_Corresponding_Transaction = 1 for a given TS_ID?
I was looking and found a Group by or where not exists, but couldn't figure out how to get that to work
Here's an e.g. of what I tried:
select
Full_Name, amount, a.Posted_Date,a.Payee_Name, a.Memo, Accounts.Account_Name
from AccountTransaction a
left join Accounts on Accounts.Account_Code = a.Account_Code
left join users on a.UserId = users.UserId
where not exists (select 1 from AccountTransaction b where a.Transaction_ID = b.Transaction_ID having count(*)>1)
and a.Pending= 0
ORDER by a.Posted_Date desc
Just to expand on Stu's comment. Here is one option that uses the window function
with cte as (
Select *
,NetSum = sum(Amount) over (partition by Transaction_ID)
,NetCnt = sum(1) over (partition by Transaction_ID)
From YourTable
)
Select *
From cte
Where NetSum<>0
or NetCnt<>2
I would like to get an output which displays the personID and the total sum of books the user has made throughout every loan.
Member:
PersonID
1
2
Loan:
PersonID
LoanID
1
1
1
2
2
3
OrderLine:
LoanID
BookID
1
1
1
2
1
3
2
4
2
5
3
6
3
7
Expected output:
PersonID
Total sum of books
1
5
2
2
Edit:
I have tried a couple of things, as I've been at this for about three hours now. Most of my attempts have been scrapped but this is one attempt I came up with which wasn't able to do my problem.
SELECT SUM(TOTAL) AS Test FROM (
SELECT COUNT(*) AS TOTAL FROM Person AS P
WHERE P.PersonID IN (
SELECT PersonID FROM Loan AS L
WHERE L.LoanID IN (
SELECT LoanID FROM Orderline AS OL
WHERE L.LoanID = OL.LoanID
)
)
GROUP BY P.PersonID
) AS TOTAL;
If you want to count duplicated books :
SELECT
PersonID,
count(*) as 'Total sum of books'
FROM
Loan l
INNER JOIN
OrderLine o on l.LoanID = o.LoanID
GROUP BY PersonID
For including users with 0 loan:
SELECT
m.PersonID,
CASE
WHEN c.PersonID is not NULL THEN c.cpt
ELSE 0
END as 'Total sum of books'
FROM
Member m
FULL JOIN
(
SELECT
PersonID,
count(*) as cpt
FROM
Loan l
INNER JOIN
OrderLine o on l.LoanID = o.LoanID
GROUP BY PersonID
) as c ON m.PersonId = c.PersonId
It's not the most elegant way to do it, but I think it's one of the easiest to understand.
With the full join will give you one counter (cpt) per user. If there is no match then cpt will be NULL.
I am trying to write a query using group by in sub query ,I referred lot of blogs but could not get all the values.
I have three tables and below is the structure of those tables.
Pet_Seller_Master
ps_id ps_name city_id
2 abc 1
3 xyz 2
4 fer 4
5 bbb 1
City_Master
city_id city_name
1 Bangalore
2 COIMBATORE
4 MYSORE
Api_Entry
api_id ps_id otp
1 2 yes
2 3
3 2 yes
4 3 yes
5 4
6 5 yes
7 5 yes
8 5 yes
Query is to get number of sellers, no of pet sellers with zero otp, no of pet sellers with 1 otp, no of pet sellers with 2 otp,no of pet sellers with otp>2 for the particular city and within date range.
Through Below query I am able to get city , psp , and zero otp
select cm.city_name,
count(ps.ps_id) as PSP,
((select count(ps1.ps_id)
FROM ps_master ps1
WHERE ps1.city = cm.city_id)-
(SELECT count(distinct ps1.ps_id)
from ps_master ps1
INNER JOIN api_entry ae ON ps1.ps_id = ae.ps_id and otp!=''
WHERE ps1.city = cm.city_id and date(timestamp) >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY AND date(timestamp) < curdate())) as zero_psp
from ps_master ps INNER JOIN city_master cm ON ps.city = cm.city_id and cm.city_type = 'IN HOUSE PNS'
group by city_id
Please tell me the solution to solve this query.
Thanks in advance
It's not hard to do and you were on a right track. Here is what I would use:
select c.city_name, a.otp, p.ps_name, COUNT(*) nbr
from Api_Entry a
inner join Pet_Seller_Master p on p.ps_id=a.ps_id
inner join City_Master c on p.city_id=c.city_id
group by c.city_name, a.otp, p.ps_name
Now, if you want to get the number of sellers with zero otp, you just apply where clause:
where otp <> 'yes'
If you want to get the number of pet sellers with otp>2, then you just use subquery:
select *
from (
select c.city_name, a.otp, p.ps_name, COUNT(*) nbr
from #tempA a
inner join #tempP p on p.ps_id=a.ps_id
inner join #tempC c on p.city_id=c.city_id
group by c.city_name, a.otp, p.ps_name
) g
where nbr > 2
I Have 3 tables Customer, Bank and BankTransaction.
On My View I want to display each customer with their Balance in the bank account.
Here is my tables
Customer
Id Name
---------
1 John
2 Jack
Bank
Id CustomerId BankName
----------------------------------
1 1 HSBC
2 2 HSBC
BankTransaction
Id BankID MoneyIn MoneyOut Balance
---------------------------------------------
1 1 1000 0 1000
2 1 0 500 500
3 2 2000 0 2000
4 2 2000 0 4000
5 2 1000 0 5000
Now I want to Display following data view query
John 500
Jack 5000
Last Balance of each customer
Try this
SELECT A.Name,
Sum(C.MoneyIN) - Sum(C.MoneyOut) AS Balance
FROM #Customer A
JOIN #Bank B ON A.Id = B.id
JOIN #BankTransaction C ON B.Id = C.BankID
GROUP BY A.Name
Using Window function you can get the result. Try this.
;WITH cte
AS (SELECT Row_number() OVER (partition BY b.id ORDER BY a.id DESC) rn,
c.Name,
a.balance
FROM BankTransaction a
JOIN bank b ON a.BankID = b.Id
JOIN Customer c ON c.Id = b.CustomerId)
SELECT name, balance
FROM cte
WHERE rn = 1
I have two tables as follows:
Table A
Docnumber Line Amount Doctype
1000 1 100 3
1000 2 200 3
1001 1 300 5
Table B
Docnumber Debit Credit Account
1000 100 0 5410
1000 200 0 5560
1001 0 300 6790
I'm trying to create a select which looks like this:
Docnumber Line Amount Account
1000 1 100 5410
1000 2 200 5560
1001 1 300 6790
So, logically, I'm trying to figure out a way to join A.Amount to B.Debit where A.Doctype = 3 and join A.Amount to B.Credit where A.Doctype = 5
As you can see, I'm a novice but any help would be greatly appreciated
Assuming SQL Server. Also assuming that Docnumber is intended to play a role in your JOIN as well, despite not being explicitly stated in the question.
You can use any conditions on the JOIN that you want:
SELECT A.Docnumber, A.Line, A.Amount, B.Account
FROM A JOIN B
ON A.Docnumber = B.Docnumber
AND ((A.Doctype = 3 AND A.Amount = B.Debit)
OR (A.Doctype = 5 AND A.Amount = B.Credit))
ORDER BY A.Docnumber, A.Line;
Alternatively, you could put it into the WHERE clause, which is probably more clear:
SELECT A.Docnumber, A.Line, A.Amount, B.Account
FROM A JOIN B ON A.Docnumber = B.Docnumber
WHERE (A.Doctype = 3 AND A.Amount = B.Debit) OR (A.Doctype = 5 AND A.Amount = B.Credit)
ORDER BY A.Docnumber, A.Line
Actually easier than you might think!
SELECT *
FROM A
INNER JOIN B
ON (A.Doctype = 3 AND B.Debit = A.Amount)
OR (A.Doctype = 5 AND B.Credit= A.Amount)