sql Query to find different record in a column - sql

I have table with 5 OR 6 COLUMNS and I need to use the below 2 columns to get the result
col1 col2
Acc1 USD
ACC1 GBP
ACC1 EUR
ACC2 USD
Result:
I need to find out if a acc has more than 2 currency, but the base currency is USD. I need to find out those records which has USD plus other currency if I have only USD accounts then it should not come in my result.

With the information provided this could be an answer:
SELECT col1
FROM tab
GROUP BY col1
HAVING count(*) > 1

Not the best solution but should do the job.
with cte as
(
SELECT t1.[col1],t1.[col2],(select count(t2.col1) from accounts t2 where t2.col1=t1.col1) as AllCurrency
from accounts t1
)
SELECT distinct cte.col1 from cte where cte.AllCurrency>1

Related

T-SQL count number of different values across multiple columns

I have an SQL database which contains a table with four different currency columns, I need to determine how many different currencies each record has across these four columns, for example..
Record ID
Curr1
Curr2
Curr3
Curr4
CurrencyCount
1
GBP
USD
GBP
GBP
2
2
GBP
EUR
GBP
USD
3
3
GBP
GBP
GBP
GBP
1
4
GBP
GBP
GBP
EUR
2
How can I determine the "CurrencyCount" / count of currencies against each record? I can't think how to approach this
Thank you for any help
You can use a Table Value Constructor referencing columns from the outer row and then COUNT (DISTINCT - no need for any expanding out and collapsing with GROUP BY
SELECT *,
CurrrencyCount = (SELECT COUNT (DISTINCT Currency) FROM (VALUES (CURR1), (CURR2), (CURR3), (CURR4)) AS x (Currency))
FROM YourTable
This would do the work. But not sure how will be the performance if there is a large amount of data.
WITH CTE as (
SELECT '1' as RecID,'GBP' as CURR1,'USD' as CURR2,'GBP' as CURR3, 'GBP' as CURR4
UNION ALL
SELECT '2' ,'GBP' ,'EUR' ,'GBP','USD'
UNION ALL
SELECT '3' ,'GBP' ,'GBP' ,'GBP','GBP'
UNION ALL
SELECT '4' ,'GBP' ,'GBP' ,'GBP','EUR'
)
SELECT
RecID
,CURR1,CURR2,CURR3,CURR4
,COUNT(DISTINCT Currency) as CurrrencyCount
FROM CTE
CROSS APPLY (VALUES (CURR1), (CURR2), (CURR3), (CURR4)) as x (Currency)
GROUP BY RecID,CURR1,CURR2,CURR3,CURR4
Only run this its also work
SELECT
RecordID
,Curr1,Curr2,Curr3,Curr4
,COUNT(DISTINCT Currency) as Currency
FROM [TABLE_NAME]
CROSS APPLY (VALUES (Curr1), (Curr2), (Curr3),(Curr4)) as x (Currency)
GROUP BY RecordID,Curr1,Curr2,Curr3,Curr4

Link on two tables if not all values between fields match in PostgreSQL?

I have two tables
exchange_rates:
curr1 curr2 rate
USD GBP 0.81
EUR GBP 0.98
transactions
TIMESTAMP user curr amt
2017-01-01 u1 EUR 89
2017-01-01 u2 GBP 3
2017-01-03 u2 USD 10
I want to link exchange_rates and transactions and multiply amt by the corresponding exchange rate in GBP in exchange_rates. e.g. in line 3 of transactions we would multiply 10 by 0.81 to get 8.1. BUT if the amount is in GBP in the transactions table I want to leave that unchanged.
I have tried to use CASE and link the two table like this
select
trans.TIMESTAMP, trans.user
case
when trans.currency != "GBP" then trans.amt*er.rate
else trans.amt
end as "Converted Amount"
from exchange_rates er, transactions trans
where trans.curr = er.curr1
But this doesn't work when curr in transactions is GBP (line 2) since there is not curr1=GBP in exchange_rates... can anyone advise what the logic would be here to solve this?
DESIRED RESULT:
TIMESTAMP user converted amt
2017-01-01 u1 87.22
2017-01-01 u2 3
2017-01-03 u2 8.1
Simply add a record in exchange_rates that defines a 1 to 1 exchange rate for GBP:
curr1 curr2 rate
GBP GBP 1
Aside from that you can also use a left outer join to include all the matching records in the source table, regardless if the joined table matched: http://www.postgresqltutorial.com/postgresql-left-join/
select
trans.TIMESTAMP, trans.user,
trans.amt * coalesce(er.rate, 1) as "Converted Amount"
from transactions trans
left join exchange_rates er on er.curr1 = trans.curr
I think you want something like this:
select t.TIMESTAMP, t.user,
t.amt * coalesce(er.rate, 1) as converted_amount
from transactions t left join
exchange_rates er
on t.curr = er.curr1 and er.curr2 = 'GBP';
Why does this look a bit different from your query?
First, it uses a left join. Second, it compares both currencies. It also simplifies the logic for the lookup.

Select entire row with more than one distinct column

I have a table based on invoice items where I am trying to use SQL to detect at what dates the price or currency for the combination of material/customer has changed. The table contains invoices for several customers although the materials can be common.
My SQL skills are quite basic and I have tried several different approaches using GROUP BY and DISTINCT that I have found in other threads but I always seem to get stuck somewhere along the way.
This is basically what the data looks like:
Invoice Inv. Date Material Price Currency Per/Qty Customer
SE100 20140901 111111 1 EUR 1 840006
SE100 20140901 222222 2 EUR 1000 840006
SE100 20140901 333333 3 USD 1 840006
SE101 20140902 111111 1 EUR 1 840006
SE101 20140902 222222 2 EUR 1000 840006
SE101 20140902 333333 3 USD 1 840006
SE102 20140903 111111 2 EUR 1 840006
SE102 20140903 222222 2 USD 1000 840006
SE102 20140903 333333 3 USD 1 840006
SE103 20140904 111111 1 EUR 1 840006
SE103 20140904 222222 2 USD 1000 840006
SE103 20140904 333333 3 USD 1 840006
What I want to accomplish is basically to select the first row datewise for all distinct combinations of Customer/Material/Currency/Price and then subselect the entire rows (sorted by material) for those materials that occur more than once in the selection, thus indicating the price or currency has changed from the initial value.
The expected output from the query using the data in the table above would then look something like this:
Invoice Inv. Date Material Price Currency Per/Qty Customer
SE100 20140901 111111 1 EUR 1 840006
SE102 20140903 111111 2 EUR 1 840006
SE103 20140904 111111 1 EUR 1 840006
SE100 20140901 222222 2 EUR 1000 840006
SE102 20140903 222222 2 USD 1000 840006
I hope I managed to explain the problem in an understandable way. The database engine is SQL Server 2005 Express.
Any help would be appreciated...
The key word DISTINCT in SQL has the meaning of "unique value". When applied to a column in a query it will return as many rows from the result set as there are unique, different values for that column. As a consequence it creates a grouped result set, and values of other columns are random unless defined by other functions (such as max, min, average, etc.)
If you meant to say you want to return all rows for which Col 06 has a specific value, then use the "where Col 06 = value" clause
SELECT mt.*
FROM (
SELECT DISTINCT col6
FROM mytable
) mto
JOIN mytable mt
ON mt.id =
(
SELECT TOP 1 id
FROM mytable mti
WHERE mti.col6 = mto.col6
-- ORDER BY
-- id
-- Uncomment the lines above if the order matters
)
I think this is a direct translation of what you want:
select t.*
from mydata t join
(select Customer, Material, count(distinct price) as numprices
from mydata
group by Customer, Material
having count(distinct price) > 1
) cmcp
on t.customer = cmcp.customer and t.material = cmcp.material;
This leaves out the currency. Unfortunately, SQL Server doesn't support multiple arguments to distinct. You can include it this way:
select t.*
from mydata t join
(select Customer, Material,
count(distinct cast(price as varchar(255)) + ':' + currency) as numprices
from mydata
group by Customer, Material
having count(distinct cast(price as varchar(255)) + ':' + currency) > 1
) cmcp
on t.customer = cmcp.customer and t.material = cmcp.material;
Most databases support window/analytic functions, so you can also phrase this as:
select t.*
from (select t.*,
min(cast(price as varchar(255)) + ':' + currency)) over (partition by Customer, Material) as minprice,
max(cast(price as varchar(255)) + ':' + currency)) over (partition by Customer, Material) as maxprice
from mydata t
) t
where minprice <> maxprice
order by Material, Inv_Date;

How to display rows that when added together equal zero

Been searching for a few weeks for a solution to this but have come up blank.
I have table of data similar to this:
client_ref supplier_key client_amount
1111 GBP 10
1111 GBP -10
1111 EUR 50
2222 CHF -22.5
2222 CHF -20
3333 EUR -27
3333 EUR -52
3333 EUR 79
I need to extract all items where the client_ref and supplier_key match and the total of the client_amount equals zero. The output would look like this:
client_ref supplier_key client_amount
1111 GBP 10
1111 GBP -10
3333 EUR -27
3333 EUR -52
3333 EUR 79
I have written the following that returns the totals but I need any help you could provide to change this to show the rows that make up the totals rather than just the overall results.
SELECT tbis.client_ref ,tbis.supplier_key ,sum(tbis.client_amount)
FROM [XXXX].[dbo].[transaction] tbis
WHERE tbis.tbis.client_amount !=0
GROUP BY tbis.client_ref, tbis.supplier_key
HAVING sum(tbis.client_amount) =0
ORDER BY sum(tbis.client_amount)
Hope this makes sense and my first post is OK. Please feel free to critique my post.
Try this instead:
SELECT t1.*
FROM transactions AS t1
INNER JOIN
(
SELECT
tbis.client_ref ,
tbis.supplier_key,
sum(tbis.client_amount) AS total
FROM transactions tbis
WHERE tbis.client_amount !=0
GROUP BY tbis.client_ref, tbis.supplier_key
HAVING sum(tbis.client_amount) =0
) AS t2 ON t1.client_ref = t2.client_ref
AND t1.supplier_key = t2.supplier_key
ORDER BY t2.total;
SQL Fiddle Demo
One possible approach is to use the SUM() windowing function:
SELECT *
FROM
( SELECT tbis.client_ref ,tbis.supplier_key,tbis.client_amount,
SUM(tbis.client_amount) OVER (
PARTITION BY tbis.client_ref, tbis.supplier_key) AS total_client_amount
FROM [XXXX].[dbo].[transaction] tbis
WHERE tbis.client_amount !=0
)
WHERE total_client_amount = 0
SQL Fiddle
SELECT client_ref ,supplier_key ,sum(client_amount)
FROM transaction
WHERE client_amount <> 0
GROUP BY client_ref, supplier_key
HAVING sum(client_amount) = 0
SELECT
*
FROM
tbis
INNER JOIN
(
SELECT
client_ref, supplier_key
FROM
tbis
GROUP by client_ref, supplier_key
HAVING sum(client_amount) = 0
) match
ON match.client_ref = tbis.client_ref
AND match.supplier_key = tbis.supplier_key
Demo at http://sqlfiddle.com/#!3/a3447/8/0
SELECT t.* FROM Table1 AS t INNER JOIN
(SELECT [client_ref], [supplier_key], SUM([client_amount]) as Total
FROM Table1 GROUP BY [client_ref], [supplier_key]) AS sumTable
ON t.[client_ref] = sumTable.[client_ref] AND
t.[supplier_key] = sumTable.[supplier_key]
WHERE Total = 0;
SAMPLE FIDDLE
Make a new query for the data you want and join it by inner join to the query that produces the sums to restrict it to the lines you want.

Multiply 2 values from 2 different tables

I'm trying to multiply value X by value Y with SQL. Value X is located in table A and B is located in table B. I couldn't find the answer for this.
Table Transactions
ID Transaction_ID Total_Amount
1 001 1200
2 002 1500
3 003 1600
Table Rates
ID Currency_Name Exchange_Rate
1 AUD 1.5
2 SEK 2.0
3 PLN 3.0
The question I'm trying to answer is:
What is the Total_Amount for transaction 001 in SEK (Swedish Crown). So I need to multiply 1200 * 2.0 and display the result.
Edited based on added info
SELECT Total_Amount * Exchange_Rate AS Value
FROM Transactions, Rates
WHERE Rates.Currency_Name = 'Sek' and Transaction_id = 001
To answer your question:
What is the Total_Amount for
transaction 001 in SEK (Swedish
Crown). So I need to multiply 1200 *
2.0 and display the result.
Use:
SELECT ID, Transaction_ID, Total_Amount, Total_Amount*(SELECT Exchange_Rate from Rates where Currency_Name='SEK')
FROM TRANSACTIONS
WHERE TRANSACTION_ID='001'
This should work, depending on your table structure :
select table1.x * table2.y
from table1, table2;
But I actually doubt that this is really what you want to do, if you provide more information, we could give you a much better answer. Please provide table structure and you're real goal !
how about this:
select a.x*b.y from tableA a, tableB b