How to display datas in a table in the columns in a query from another table? - ms-access

In access 2016, I have 3 tables :
TbProducts
productId | descriptionProduct
1 | PC1
2 | PC2
TbCaracteristics
CaracId | DescriptionCarac
1 | Motherboard size
2 | Processor
3 | Color
4 | Size
TbCaracteristicsProducts
productId | CaracId | Value
1 | 1 | ATX
1 | 2 | i5
1 | 3 | Black
1 | 4 | Big tower
2 | 1 | MiniITX
2 | 2 | i7
2 | 3 | Blue
2 | 4 | Big tower
What I would want to display :
Product | Motherboard size | Processor | Color | Size
PC1 | ATX | i5 | Black | Big tower
PC2 | MiniITX | i7 | Blue | Big tower
I tried making a query to have a list of caracteristics but I have no idea how to put them in columns in another, nor linking the informations from a third table... Any idea ?
I also tried to use min(value) and max(value), but the problem is I have more than 2 caracteristics.

Looks like a basic JOIN and CROSSTAB.
TRANSFORM First(TbCaracteristicsProducts.Value) AS FV
SELECT TbProducts.descriptionProduct
FROM (TbCaracteristics INNER JOIN TbCaracteristicsProducts ON TbCaracteristics.CaracID = TbCaracteristicsProducts.CaracId)
INNER JOIN TbProducts ON TbCaracteristicsProducts.ProductId = TbProducts.ProductID
GROUP BY TbProducts.descriptionProduct
PIVOT TbCaracteristics.DescriptionCarac;
BTW, misspelling "caracteristic" - missing the "h".

Related

SQL Self join table, defaulting to null and removing duplicates

I have an SQL model (MySQL v8.0.20) that describes a physical card with 1 or 2 faces. Because card faces can appear on multiple physical cards, I've modeled this as a many-many relationship using the join table cardFaces.
I'm now trying to get a list of distinct front facing cards. That is if a card has only 1 face, it would be represented once, if it has 2 faces, it would be represented twice (once for each side front facing).
Input
The join table currently looks like this (simplified for question):
SELECT * FROM cardFaces;
+----+--------+--------+
| id | cardId | faceId |
+----+--------+--------+
| 1 | A | 1 |
| 2 | B | 2 |
| 3 | B | 3 |
+----+--------+--------+
Expected Output
The result I'm expecting to achieve is this:
+--------+-------------+------------+
| cardId | frontFaceId | backFaceId |
+--------+-------------+------------+
| A | 1 | NULL |
| B | 2 | 3 |
| B | 3 | 2 |
+--------+-------------+------------+
Current Output
I've only gotten so far as self-joining and removing duplicates, but I can't figure out how to introduce NULL as the backFaceId for cards with only 1 face.
SELECT frontFace.cardId, frontFace.faceId frontFaceId, backFace.faceId backFaceId
FROM cardFaces frontFace
LEFT JOIN cardFaces backFace
ON frontFace.cardId = backFace.cardId
WHERE backFace.id != frontFace.id;
+--------+-------------+------------+
| cardId | frontFaceId | backFaceId |
+--------+-------------+------------+
| B | 2 | 3 |
| B | 3 | 2 |
+--------+-------------+------------+
Move the where condition to the on clause:
SELECT frontFace.cardId, frontFace.faceId frontFaceId, backFace.faceId backFaceId
FROM cardFaces frontFace LEFT JOIN
cardFaces backFace
ON frontFace.cardId = backFace.cardId AND
backFace.id <> frontFace.id;
NULLs fail almost all comparisons, including <>, turning the outer join into an inner join.

MySql Join two tables with multiple columns

I have two tables
tblcities:
id | name
----------------
1 | Bahawalpur
2 | Multan
3 | Karachi
4 | Lahore
tblflights:
id | from_city_id | to_city_id
-------------------------------
1 | 1 | 2
2 | 3 | 4
3 | 2 | 1
I want to join tables so it shows the city name for both columns i.e: from_city_id & to_city_id
what i tried:
SELECT *
FROM tblflights
JOIN tblcities
ON tblflights.from_city_id = tblcities.id
result:
id | from_city_id | to_city_id | name
--------------------------------------------
1 | 1 | 2 | Bahawalpur
2 | 3 | 4 | Karachi
3 | 2 | 1 | Multan
but i want name of both cities (from_city_id & to_city_id)
i tried my best but could not found any solution.
i am using CodeIgniter
Try something like this.
SELECT tf.id, tc1.name from_city_name, tc2.name to_city_name
FROM tblflights tf
JOIN tblcities tc1
ON tf.from_city_id = tc1.id
JOIN tblcities tc2
ON tf.from_city_id = tc2.id;
You may need to remove duplicates depending on your table contents.

How can I group by latest dates and IDs, yet take into account all data from previous dates?

So my example table is like this -
I have a mysql version 5.7 database which I can connect to. Read-only rights.
My table goes like this:
human_id | dog_id | dog_bought_at | amount_paid_for_dog | purchase_place | buyer_has_criminal_past
1 | 1 | 27-12-2019 | 100 | Tokyo | 0
1 | 2 | 03-01-2020 | 200 | Moscow | 0
2 | 3 | 03-01-2020 | 200 | Los Angeles | 0
3 | 4 | 03-01-2020 | 50 | Washington | 0
3 | 3 | 05-01-2020 | 30 | Dallas | 0
4 | 2 | 06-01-2020 | 150 | Texas | 1
What I need to show is this:
dog_id | last_owner_id | total_amount_paid_for_dog | last_purchase_date | last_purchase_place
1 | 1 | 100 | 27-12-2019 | Tokyo
2 | 4 | 350 | 06-01-2020 | Moscow
3 | 3 | 230 | 05-01-2020 | Dallas
4 | 3 | 50 | 03-01-2020 | Washington
Last_purchase_place is shown only for those humans, which do not have criminal past.
what I have tried:
SELECT
e.dog_id
,MAX(e.human_id) last_owner_id
,SUM(e.amount_paid_for_dog) total_amount_paid_for_dog
,MAX(e.dog_bought_at) last_purchase_date
,e_filter.purchase_place last_purchase_place
FROM example e
LEFT JOIN (
SELECT
dog_id
,dog_bought_at
,purchase_place
,human_id
FROM example
WHERE buyer_has_criminal_past != 1
) e_filter ON e.dog_id = e_filter.dog_id AND e.dog_bought_at = e_filter.dog_bought_at
But I am stuck on the logic, that allows to sum up ALL amounts, yet filter out unneeded values.
This is my first question here, so if this is a duplicate or not well written, please say it. Any help appreciated.
SELECT e1.dog_id,
e1.human_id last_owner_id,
sq1.total_amount_paid_for_dog,
e1.dog_bought_at last_purchase_date,
e2.purchase_place last_purchase_place
FROM example e1
JOIN ( SELECT dog_id,
MAX(dog_bought_at) dog_bought_at,
SUM(amount_paid_for_dog) total_amount_paid_for_dog
FROM example
GROUP BY dog_id ) sq1 ON e1.dog_id = sq1.dog_id
AND e1.dog_bought_at = sq1.dog_bought_at
LEFT JOIN example e2 ON e1.dog_id = e2.dog_id
JOIN ( SELECT dog_id,
MAX(dog_bought_at) dog_bought_at
FROM example
WHERE buyer_has_criminal_past = 0
GROUP BY dog_id ) sq2 ON e2.dog_id = sq2.dog_id
AND e2.dog_bought_at = sq2.dog_bought_at
fiddle

How to display the string values of a table refering to Two foreign ID keys on the main table

So I have this database
TABLE: rates
ID | FID | TID | RATE
---------------------------
1 | 1 | 2 | 0.3
2 | 1 | 3 | 1.2
3 | 1 | 4 | 4.5
4 | 2 | 1 | 1.3
5 | 2 | 3 | 3.3
6 | 2 | 4 | 4.4
TABLE: currencies
ID | Name | Symbol
---------------------
1 | Euro | E
2 | Pound | P
3 | Dollar | $
4 | CAD | C
So what I tried so far was
SELECT rates.*,
currencies.name,
currencies.symbol FROM RATES
JOIN CURRENCIES ON
(rates.fid = currencies.id)
Which worked but only for 1 column. I could not find a way to add more. Also I want to give a custom output name for each currency. So the final output should be:
ID | FromCurrency (FID) | ToCurrency (TID) | Rate
You need to do multiple joins, and as you are using the same table for both joins, give them an alias.
Something like this:
SELECT rates.ID,
a.name AS 'FromCurrency (FID)',
a.symbol AS 'FID Symbol',
b.name AS 'ToCurrency (TID)',
b.symbol AS 'TID Symbol',
rates.rate
FROM RATES
JOIN CURRENCIES AS a ON
(rates.fid = a.id)
JOIN CURRENCIES AS b ON
(rates.tid = b.id)
Here is a working example

select query to calculate number of occurrence as well as total cost

I have one report page which displays summarized data of other report.I have used php and mysqli. Let me explain you in deep.
I have a web application of store, where you can add product details. Using these product details you can generate packaging list report of products. And based on the generated packaging list report I need to generate one other report which contains summarized data of the packaging list.
below are my tables:
product table:
id | name | desc_id | purity | style_no | type | duty
1 | ABC | 1 | 18 | TEST123 | R | 100
2 | XYZ | 2 | 14 | TEST456 | B | 80
3 | DEF | 1 | 14 | TEST122 | R | 80
4 | PQR | 1 | 18 | TEST124 | R | 120
5 | HJK | 3 | 18 | TEST134 | B | 300
Description table:
id | descrip
1 | Gold Diamond Ring
2 | Gold Diamond Pendant
3 | Gold Diamond Earring
packaging_master table
id | name
1 | pkg_1
2 | pkg_2
packging_details table
id | pkg_id | prod_id
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 1 | 4
5 | 1 | 5
I have used below query to generate the packaging list report for specific id, which works correctly.
SELECT id, (SELECT descrip FROM description WHERE id = desc_id ) AS descrip,
style_no, type , purity, duty FROM product WHERE id IN ( SELECT prod_id FROM packaging_list_details WHERE pkg_id =1 ) ORDER BY descrip ASC , purity ASC
which displays below result:
id | descrip | style_no | type | purity | duty
1 |Gold Diamond Ring | TEST123 | R | 18 | 100
4 |Gold Diamond Ring | TEST124 | R | 18 | 120
3 |Gold Diamond Ring | TEST122 | R | 14 | 80
2 |Gold Diamond Pendant| TEST456 | B | 14 | 80
5 |Gold Diamond Earring| TEST134 | B | 18 | 300
Now I want summarized data of above result using query.
Like:
id | descrip | purity | qty | duty
1 |Gold Diamond Ring | 18 | 2 | 220
2 |Gold Diamond Ring | 14 | 1 | 80
3 |Gold Diamond Pendant| 14 | 1 | 80
4 |Gold Diamond Earring| 18 | 1 | 300
How can I achieve this?
You need to use the GROUP_BY statement - See MySql docs for more info.
This will translate the query to such
SELECT d.descrip, p.purity, count(p.purity) as qty, sum(p.duty)
FROM product p
INNER JOIN Description d ON p.desc_id = d.id
LEFT OUTER JOIN packaging_details pg on pg.prod_id = p.id
GROUP BY d.descrip, p.purity
ORDER BY d.descrip desc, p.purity desc
You can also use the sub select methodology you were using, but I prefer using joins. INNER JOIN will link both tables so that all their records are returned. OUTER JOIN will return all rows from the tables on the LEFT of the statement and matches them to values from the tables on the RIGHT.
See a full SQL Fiddle sample.
NOTE: I am not sure where you are getting the values for Id in your sample - Are they simply row numbers?
I think you should rewrite your query using JOINs:
SELECT
P.id
,D.descrip
,P.style_no
,P.type
,P.purity
,P.duty
FROM
packaging_list_details PLD
JOIN
product P ON
(P.id = PLD.prod_id)
LEFT JOIN
description D on
(D.desc_id = P.id)
WHERE
(PLID.pkg_id = 1)
That should give you the same result you already have. To get the totals, you can write a new query, similar to the above:
SELECT
P.id
,D.descrip
,P.type
,P.purity
,COUNT(p.id) as total_products
,SUM(P.duty) as total_duty
FROM
packaging_list_details PLD
JOIN
product P ON
(P.id = PLD.prod_id)
LEFT JOIN
description D on
(D.desc_id = P.id)
WHERE
(PLID.pkg_id = 1)
GROUP BY
P.id
,D.descrip
,P.type
,P.purity
The second query gives you the totals you are looking for.