Postgres query issue [duplicate] - sql

This question already has an answer here:
Complex Postgres query
(1 answer)
Closed 7 years ago.
The db schema along with sample data is something like this -
(Country table)
| Country | Country Code |
--------------------------
ABC A
BCD B
(TransactionTable)
| SrcCountryCode | DestCountryCode| SrcCurrency| DestCurrency | SrcAmount | DestAmount |
----------------------------------------------------------------------------------------
A B X Y 200 1000
A B X Y 300 1500
B A Y X 1000 200
I want the result set to be like this -
| Corridor | Total Src Amount| Total Dest Amount | Src Currency |
-----------------------------------------------------------------
ABC-BCD 500 200 X
BCD-ABC 1000 2500 Y
I am lost on how to map the Country combinations as well as map the total amounts for destination and source subsequently in one table.
Help would be appreciated.

This sql query like this
select
d.Country+'-'+e.Country as Corridor,
TotalSrcAmount,
TotalDestAmount,
SrcCurrency
from TransactionTable a
join
(
select SrcCurrency ,sum(SrcAmount) 'TotalSrcAmount'
from TransactionTable
Group by SrcCurrency
)b on a.SrcCurrency =b.SrcCurrency
join
(
select DestCurrency,sum(DestAmount) 'TotalDestAmount'
from TransactionTable
Group by DestCurrency
)c on a.SrcCurrency =c.DestCurrency
join Countrytable d on d.Country_Code=a.SrcCountryCode
join Countrytable e on e.Country_Code=a.DestCountryCode
group by
d.country,
e.country,
a.SrcCurrency

Related

Sum of two tables using SQL

I'm trying to get the sum of two columns, but it seems to be adding incorrectly. I have a table Tbl_Booths and another table called Tbl_Extras.
In the Tbl_Booths:
BoothId | ExhId | BoothPrice
1 | 1 | 400
2 | 1 | 500
3 | 2 | 400
4 | 3 | 600
So totalBoothPrice for ExhId = 1 is 900
Tbl_Extras:
ExtraId | ExhId | Item | ItemCost
1 | 1 | PowerSupply | 400
2 | 2 | PowerSupply | 400
3 | 1 | Lights | 600
4 | 3 | PowerSupply | 400
5 | 4 | Lights | 400
So totalItemCost for ExhId = 1 is 1000
I need to find a way to get the sum of totalBoothPrice + totalItemCost
The value should of course be 900 + 1000 = 1900
I'm a total beginner to SQL so please have patience :-)
Thank you in advance for any input you can give me, since I'm going made here !
It is used in a Caspio database system.
You can use union all to combine the two tables and then aggregate:
select exhid, sum(price)
from ((select exhid, boothprice as price
from tbl_booths
) union all
(select exhid, itemcost as price
from tbl_extras
)
) e
group by exhid;
This returns the sum for all exhid values. If you want to filter them, then you can use a where clause in either the outer query or both subqueries.
Here is a db<>fiddle.
Booth totals:
select exhid, sum(boothprice) as total_booth_price
from tbl_booths
group by exhid;
Extra totals:
select exhid, sum(itemcost) as total_item_cost
from tbl_extras
group by exhid;
Joined:
select
exhid,
b.total_booth_price,
e.total_item_cost,
b.total_booth_price + e.total_item_cost as total
from
(
select exhid, sum(boothprice) as total_booth_price
from tbl_booths
group by exhid
) b
join
(
select exhid, sum(itemcost) as total_item_cost
from tbl_extras
group by exhid
) e using (exhid)
order by exhid;
This only shows exhids that have both booth and extras, though. If one can be missing use a left outer join. If one or the other can be missing, you'd want a full outer join, which MySQL doesn't support.

how to divide the amount for each record on specific condition

I have a table let's assume X
and I want to join it to another table Y
this the content of X
ID | value
------------------
100 | -500
200 | 45
300 | -100
table Y
ID | store_code
---------------------
100 | 7001
100 | 7002
100 | 7003
200 | 3001
200 | 3002
300 | 5001
If I made a relationship between X & Y tables
the amount it will be duplicated, so if I used sum function the total will be wrong
I decided to divide the amount between the stores for each ID
for example
the amount for ID 200 will be like this
ID | store_code | amount
200 | 3001 | 22.5
200 | 3002 | 22.5
when I use sum function the result will return to its original value 45
how can I do this calculation in SQL code?
Hmmm . . . If I understand correctly, you want to allocate the full value over multiple rows. Use window functions:
select y.id, y.store_code,
(x.value / count(*) over (partition by y.id)) as amount
from x join
y
on x.id = y.id
Try this:
Select id, store_code, value/count amount
from(select x.id, y.store_code, y.value,
count(x.id) OVER (PARTITION BY store_code) count
from x JOIN y ON x.id = y.id)
Looks like you need to aggregate that?
If yes, you can just add X.value into group-by list and select-list as-is.

SQL select only highest date

For a project I want to generate a price list.
I want to get only the latest prices from each supplier for each article.
There are just those two tables.
Table articles
ARTNR | TXT | ACTIVE | SUPPLIER
------------------------------------------
10 | APPLE | Y | 10
20 | ORANGE | Y | 10
30 | KEYBOARD | N | 20
40 | ORANGE | Y | 20
50 | BANANA | Y | 10
60 | CHERRY | Y | 10
Table prices
ARTNR | PRCGRP | PRCDAT | PRICE
--------------------------------------
10 | 10 | 01-Aug-10 | 2.1
10 | 10 | 05-Aug-11 | 2.2
10 | 10 | 21-Aug-12 | 2.5
20 | 0 | 01-Aug-10 | 2.1
20 | 10 | 09-Aug-12 | 2.3
10 | 10 | 14-Aug-13 | 2.7
This is what I have so far:
SELECT
ARTICLES.[ARTNR], ARTICLES.[TXT], ARTICLES.[ACTIVE], ARTICLES.[SUPPLIER], PRICES.PRCGRP, PRICES.PRCDAT, PRICES.PRICE
FROM
ARTICLES INNER JOIN PRICES ON ARTICLES.ARTNR = PRICES.ARTNR
WHERE
(
(ARTICLES.[ACTIVE]="Y") AND
(ARTICLES.[SUPPLIER]=10) AND
(PRICES.PRCGRP=0) AND
(PRICES.PRCDAT=(SELECT MAX(PRCDAT) FROM PRICES as art WHERE art.ARTNR = PRICES.artnr) )
)
ORDER BY ARTICLES.ARTNR
;
It is okay to choose just one supplier each time, but I want the max price.
The problem is:
Lots of articles do not show up with the query above,
but I cannot figure out what is wrong.
I can see that they should be in the resultset when I leave out the subselect on max prcdat.
What is wrong?
Your subquery to get the latest price does not take the other conditions into account, that is when you're getting the latest price, you may get a price in another price group or that is not active. When you join that against the filtered list that has no inactive prices and only prices in a single price group, you get no hits that exist in both.
Either you need to duplicate or - better - move your conditions inside the subquery to get the best price under the conditions. I can't test against access, but something like this should be possible if the SQL is not too limited;
SELECT a.artnr, a.txt, a.active, a.supplier, p.prcgrp, p.prcdat, p.price
FROM articles a INNER JOIN prices p ON a.ARTNR = p.ARTNR
JOIN (
SELECT a.artnr, MAX(p.prcdat) prcdat
FROM articles a JOIN prices p ON a.artnr = p.artnr
WHERE a.active='Y' AND a.supplier=10 AND p.prcgrp=10
GROUP BY a.artnr) z
ON a.artnr = z.artnr AND p.prcdat = z.prcdat
ORDER BY a.ARTNR
If the SQL support in access won't allow a join with a subquery, you can just move the conditions inside your existing subquery, something like;
SELECT a.artnr, a.txt, a.active, a.supplier, p.prcgrp, p.prcdat, p.price
FROM articles a INNER JOIN prices p ON a.ARTNR = p.ARTNR
WHERE p.prcdat = (
SELECT MAX(p2.prcdat)
FROM articles a2 JOIN prices p2 ON a2.artnr = p2.artnr
WHERE a.artnr = a2.artnr AND a2.active='Y' AND a2.supplier=10 AND p2.prcgrp=10
)
ORDER BY a.ARTNR;
Note that due to limitations in identifying a unique price (no primary key in prices), the queries may give duplicates if several prices for the same article have the same prcdat. If that's a problem, you'll probably need to duplicate your conditions outside the subquery too.

Query 3 tables in 1 query - miss the last one

I want to have the following result:
| # | Country | Percent | Nb bookings |
| 1 | France | 20% | 10 bookings |
| 2 | Canada | 80% | 8 bookings |
My actual db are like that:
Table 1: ___Kardex
KDX_Id (exemple 9)
...
KDX_PostalAddress_Country (example: FR)
Table 2: ___Bookings
BOO_Id
BOO_ClientId (link with table 1, = 9)
Table 3: ___CountryList
CTY_Code (link with table 1, = FR)
CTY_en (should show France)
My SQL query in PDO is the following:
SELECT KDX_PostalAddress_Country,
COUNT(KDX_Id) * 100 /
(SELECT COUNT(KDX_Id)
FROM ___Kardex) AS KDX_CountryPercentage,
COUNT(KDX_Id) AS KDX_CountryCount
FROM ___Kardex
WHERE KDX_HotelId=:hotel_id
GROUP BY KDX_PostalAddress_Country
ORDER BY KDX_CountryPercentage DESC
But I can't get the country name (CTY_en), just it code (KDX_PostalAddress_Country).
I have try to insert an INNER JOIN without success.
INNER JOIN ___CountryList
ON ___Kardex.KDX_PostalAddress_Country=___CountryList.CTY_Code
Could you please help me to solve this problem ?
Thanks a lot.
Have you tried this?
SELECT CTY_en,
COUNT(KDX_Id) * 100 /
(SELECT COUNT(KDX_Id)
FROM ___Kardex) AS KDX_CountryPercentage,
COUNT(KDX_Id) AS KDX_CountryCount
FROM ___Kardex
INNER JOIN ___CountryList
ON ___Kardex.KDX_PostalAddress_Country=___CountryList.CTY_Code
WHERE KDX_HotelId=:hotel_id
GROUP BY KDX_PostalAddress_Country
ORDER BY KDX_CountryPercentage DESC

join on three tables? Error in phpMyAdmin

I'm trying to use a join on three tables query I found in another post (post #5 here). When I try to use this in the SQL tab of one of my tables in phpMyAdmin, it gives me an error:
#1066 - Not unique table/alias: 'm'
The exact query I'm trying to use is:
select r.*,m.SkuAbbr, v.VoucherNbr from arrc_RedeemActivity r, arrc_Merchant m, arrc_Voucher v
LEFT OUTER JOIN arrc_Merchant m ON (r.MerchantID = m.MerchantID)
LEFT OUTER JOIN arrc_Voucher v ON (r.VoucherID = v.VoucherID)
I'm not entirely certain it will do what I need it to do or that I'm using the right kind of join (my grasp of SQL is pretty limited at this point), but I was hoping to at least see what it produced.
(What I'm trying to do, if anyone cares to assist, is get all columns from arrc_RedeemActivity, plus SkuAbbr from arrc_Merchant where the merchant IDs match in those two tables, plus VoucherNbr from arrc_Voucher where VoucherIDs match in those two tables.)
Edited to add table samples
Table arrc_RedeemActivity
RedeemID | VoucherID | MerchantID | RedeemAmt
----------------------------------------------
1 | 2 | 3 | 25
2 | 6 | 5 | 50
Table arrc_Merchant
MerchantID | SkuAbbr
---------------------
3 | abc
5 | def
Table arrc_Voucher
VoucherID | VoucherNbr
-----------------------
2 | 12345
6 | 23456
So ideally, what I'd like to get back would be:
RedeemID | VoucherID | MerchantID | RedeemAmt | SkuAbbr | VoucherNbr
-----------------------------------------------------------------------
1 | 2 | 3 | 25 | abc | 12345
2 | 2 | 5 | 50 | def | 23456
The problem was you had duplicate table references - which would work, except for that this included table aliasing.
If you want to only see rows where there are supporting records in both tables, use:
SELECT r.*,
m.SkuAbbr,
v.VoucherNbr
FROM arrc_RedeemActivity r
JOIN arrc_Merchant m ON m.merchantid = r.merchantid
JOIN arrc_Voucher v ON v.voucherid = r.voucherid
This will show NULL for the m and v references that don't have a match based on the JOIN criteria:
SELECT r.*,
m.SkuAbbr,
v.VoucherNbr
FROM arrc_RedeemActivity r
LEFT JOIN arrc_Merchant m ON m.merchantid = r.merchantid
LEFT JOIN arrc_Voucher v ON v.voucherid = r.voucherid