Access or Mysql - Table rows as columns in query - mysql

I have these three tables:
The table "Clienti" contains the customers.
The table "Corsi" contains all the available courses
The table "corsi Fatti" contains all the Courses each client has taken.
what I would need is a query that returns each client, and what courses he attended on what date.
For that I would like to have for example a table returned with these columns:
Clienti.Nome, corsi.row1.corso, corsi.row2.corso, corsi.row3.corso,corsi.rowN.corso.
and the content of the table should be:
clienti.Nome, corsifatti.data of the matching course in the corsi table if present.
so, first column is the client name, and then there is a column for each row of the "corsi" table, and if a client has partecipated on that course then the corsifatti.data should be in that column.
Can something like this be done with a Access or Mysql Query? I have tried with inner joins but the result was not what I need.
select
Clienti.nome, Clienti.Addresse, Clienti.CAP, Clienti.Tel,
Clienti.Ansprechpartner, Clienti.Mail, Clienti.Weiteres,
CorsiFatti.Data, Corsi.Corso, Corsi.Durata
from Clienti
INNER JOIN CorsiFatti on CorsiFatti.[ID Cliente] = Clienti.ID
INNER JOIN Corsi on Corsi.ID = CorsiFatti.[ID Corso]

What you are asking is a simple inner join:
select Clienti.nome, Clienti.Addresse, Clienti.CAP,
Clienti.Tel, Clienti.Ansprechpartner, Clienti.Mail,
Clienti.Weiteres,
CorsiFatti.Data,
Corsi.Corso, Corsi.Durata
from Clienti
INNER JOIN CorsiFatti on CorsiFatti.[ID Cliente] = Clienti.ID
INNER JOIN Corsi on Corsi.ID = CorsiFatti.[ID Corso]
order by Clienti.nome, Corsi.Corso;
I think you meant yours was lacking the order by only.
I wouldn't suggest using access, but if it is access anyway, then you need to have parenthseses around all those joins (peculiar I know, but it is access).

The pivot with variable columns count is complicated. I can advice simplest solution uses JSON aggregation:
SELECT
ClienteId,
Name,
JSON_ARRAYAGG(
JSON_OBJECT("Data", Data, "Corso", Corso)
) Corsi
FROM
CorsiFatti
JOIN Corsi ON Corsi.Id = CorsiFatti.CorsoId
JOIN Clienti ON Clienti.Id = CorsiFatti.clienteId
GROUP BY
ClienteId,
Name
;
Result is row for each client contains client's data at his courses as JSON string:
+===========+=========+========================================================================================+
| ClienteId | Name | Corsi |
+===========+=========+========================================================================================+
| 1 | Mr. Fix | [{"Data": "2021-01-01", "Corso": "Corso1"}, {"Data": "2021-02-01", "Corso": "Corso3"}] |
+-----------+---------+----------------------------------------------------------------------------------------+
Here you can find SQL fiddle

Related

mysql check multiple column in on statement

I am stuck in 1 left join query in which I want to check multiple columns in on statement.
By default in the database, some column is null which I want to check in the on statement.
Now the issue is when I run a query using the OR operator it only runs the 1st condition and the rest are skipped.
If I use AND operator it throws an error.
So is there any way to get data from multiple conditions?
Here is my query:
$data = "SELECT
b.book_name, b.book_id,
b.cats_id, b.cats_id1,
b.cats_id2, b.cats_id3,
b.cats_id4, b.cats_id5,
b.cats_id6,
b.book_rating,
b.book_author,
b.book_stock,
b.book_publisher,
b.book_front_img,
b.book_status,
p.publisher_id,
p.publisher_name,
a.author_id,
a.author_name,
cat.cats_id,
cat.cats_name,
cat.cats_status
FROM
`books` AS b
LEFT JOIN `publisher` AS p
ON b.book_publisher = p.publisher_id
LEFT JOIN `author` AS a
ON b.book_author = a.author_id
LEFT JOIN categorys As cat
ON b.cats_id = cat.cats_id
OR b.cats_id1 = cat.cats_id
OR b.cats_id2 = cat.cats_id
OR b.cats_id3 = cat.cats_id
OR b.cats_id4 = cat.cats_id
OR b.cats_id5 = cat.cats_id
OR b.cats_id6 = cat.cats_id
GROUP BY
b.book_name
HAVING
cat.cats_name = '$search_data'
AND b.book_status = 1
ORDER BY
$sorting
LIMIT $offset, $page_limit"
You probably don't have more than one author displayed for your multi-author books either. You are misusing MySQL's notorious nonstandard extension to GROUP BY.
To troubleshoot this kind of query, disable that extension with SET sql_mode = CONCAT_WS(',',##sql_mode, 'ONLY_FULL_GROUP_BY'), then try your query again. You'll need more terms in your GROUP BY clause.
It looks like each books row has multiple category id columns. And it looks like you want to display information from your categorys table for each of them.
Use GROUP BY b.book_id, p.publisher_id, a.author_id, cats.cats_id to prevent MySQL's bizarro handling of GROUP BY from concealing your data.
I must add this: your multiple books.cats_id columns are not the SQLish way to handle your many-to-many relationship between books and categories. In the parlance of our trade, your books table is denormalized.
What you want is a new table called books_categorys with two columns, book_id and cats_id. It's called a join table. When a row is present in that table, it means a particular book is in a particular category. It's the SQLish way of handling a setup where each book can be in zero or more categorys. Here's an explanation. MySQL join many to many single row
Then you remove all the cats_id columns from books, and retrieve the categories like this.
Then you do something like this SELECT to get the categories.
SELECT books.id, books.name,
categorys.cats_id, categorys.cats_name, categorys.cats_status
FROM books
JOIN books_categorys ON books.book_id = books_categorys.book_id
JOIN categorys ON books_categorys.cats_id = categorys.cats_id
``

How to join three table to check the data in sql?

I know how to join two tables to check data, but I not sure how to join the third table. I have tried to find solution in the online, but I can't find solution it can match my problem. Hope someone can guide me how to join the third table. Thanks.
Below is my sql code, this sql code just to join two tables:
SELECT bl.id_book_name as bl_book_name
, bl.remark as bl_remark
, bl.status as status
, bl.return_date as bl_return_date
, anb.country as anb_country
, anb.title as book_name
, bl.date_borrowed as date_borrowed
FROM book_lending bl
JOIN add_new_book anb
ON bl.id_book_name = anb.id
My third table column in the below, table name is called user, I want to join the user name:
id |name |
This is my join two tables testing result:
Since you have not provided the full structure of USER table, I can only provide you the glimpse of joining third table. You may try below code -
SELECT bl.id_book_name as bl_book_name
, bl.remark as bl_remark
, bl.status as status
, bl.return_date as bl_return_date
, anb.country as anb_country
, anb.title as book_name
, bl.date_borrowed as date_borrowed
FROM book_lending bl
JOIN add_new_book anb ON bl.id_book_name = anb.id
JOIN user u ON u.id = <USER_ID column in 1 of above 2 tables>

MySQL duplicate column on select from select

I have a few tables:
resources (which contains all the posts)
pid | usrnm | title | link | content | stitle | sdesc | at | likes
tags (which contains all the tags and an ID)
id | slug
retags (which connects the resource and it's tags)
pid | tid
I'm trying to make a search engine with which you can search by multiple tags, a search value and order the results by newest or most liked.
The SQL I use for searching by tags is:
SELECT
resources.pid, resources.title
FROM resources
INNER JOIN retags ON resources.pid = retags.pid
INNER JOIN tags ON retags.tid = tags.id
GROUP BY resources.pid
HAVING
SUM(tags.slug = 'tag-z')
AND
SUM(tags.slug = 'tag-y')
How can I apply the SQL for the search value WHERE title LIKE '%bla%' and order ORDER BY at DESC to this tag search SQL?
I tried select from select but kept gettings errors like "Duplicate column pid", "Column 'pid' in field list is ambiguous" etc
Can someone help me with this SQL? Thanks
I've tried everything in StackOverflow like using an alias for column name on oneSELECT pid as pid_ ... and even on both selects but I still kept getting the same duplicate column error.
EDIT: The SQL I've been getting errors from:
SELECT * FROM
(SELECT * FROM resources
INNER JOIN retags ON resources.pid = retags.pid
INNER JOIN tags ON retags.tid = tags.id
GROUP BY resources.pid
HAVING
SUM(tags.slug = 'A2') AND
SUM(tags.slug = 'AS')
) AS tsr WHERE tsr.title LIKE '%bla%' ORDER BY tsr.`at` DESC
This is just one of them, I've tried a lot of different types from other posts and different errors I get from them.
The WHERE clause goes before the GROUP BY:
SELECT rs.pid, rs.title
FROM resources rs JOIN
retags rt
ON rs.pid = rt.pid JOIN
tags t
ON rt.tid = t.id
WHERE rs.title LIKE '%bla%'
GROUP BY rs.pid
HAVING SUM(t.slug = 'tag-z') AND
SUM(t.slug = 'tag-y')
ORDER BY MAX(rs.at);
Strictly speaking, the MAX() is not needed in the ORDER BY assuming that pid uniquely identifies each row in resources.
My guess is that at is in multiple rows, so you need to qualify the reference with the table it comes from. Note that I introduced table aliases so the query is easier to write and to read.

Retrieving data from one table while comparing value from another table

Overview
I have two tables as can be seen below:
user_planes
----------------------------------
|id |user_id|plane_id|fuel|status|
----------------------------------
| 2 1 1 1 Ready |
----------------------------------
shop_planes
------------------------
|id |name|fuel_capacity|
------------------------
| 1 bob 3 |
------------------------
Foreign Key Primary Key
user_planes.plane_id <-> shop_planes.id
I want to be able to get every field (SELECT *) in user_planes and name and fuel_capacity based on the following criteria:
WHERE user_planes.user_id = ? - Parameter which will be added to the query through PHP.
WHERE user_planes.status = 'Ready'
WHERE user_planes.fuel < shop_planes.fuel_capacity
The Issue and My Attempts
I've tried JOIN however it retrieves data which doesn't fit that criteria, meaning it gets extra data which is from shop_planes and not user_planes.
SELECT * FROM `user_planes` WHERE fuel IN (SELECT shop_planes.fuel_capacity FROM shop_planes WHERE fuel < shop_planes.fuel_capacity) AND user_planes.user_id = 1 AND status = 'Ready'
and
SELECT * FROM `user_planes` INNER JOIN `shop_planes` ON user_planes.fuel < shop_planes.fuel_capacity AND user_planes.user_id = 1 AND user_planes.status = 'Ready'
I've searched Stackoverflow and looked through many questions but I've not been able to figure it.
I've looked up many tutorials but still can't get the desired result.
The desired result is that the query should use the data stored in user_planes to retrieve data from shop_planes while at the same time not getting any excess data from shop_planes.
Disclaimer
I really struggle using JOIN queries, I could use multiple separate queries however I wish to optimise my queries hence I'm trying to bring it in to one query.
If their isn't clarity in the question, please do say, I'll update it to the best of my ability.
Note - Is there an easy query builder option available either through phpmyadmin or an alternative software?
Thanks in advance.
Your last attempt was not a bad one, the only thing you missed there was the join criteria you described at the beginning of your post. I also moved the other filters to the where clause to better distinguish between join condition and the filters.
SELECT `user_planes`.*
FROM `user_planes`
INNER JOIN `shop_planes` ON user_planes.plane_id = shop_planes.id
WHERE user_planes.fuel < shop_planes.fuel_capacity AND user_planes.user_id = 1 AND user_planes.status = 'Ready'
First you need the base JOIN
SELECT up.* -- only user_plane fields
FROM shop_planes sp -- CREATE alias for table or field
JOIN user_planes up
ON sp.id = up.plane_id
Case 1: apply a filter in where condition with php parameter.
SELECT up.*
FROM shop_planes sp
JOIN user_planes up
ON sp.id = up.plane_id
WHERE up.user_id = ?
Case 2: apply a filter in where condition with string constant
SELECT up.*
FROM shop_planes sp
JOIN user_planes up
ON sp.id = up.plane_id
WHERE user_planes.status = 'Ready'
Case 3: aply filter comparing fields from both tables
SELECT up.*
FROM shop_planes sp
JOIN user_planes up
ON sp.id = up.plane_id
WHERE up.fuel < sp.fuel_capacity
Try something like:
SELECT
up.id AS User_Plane_ID
, up.[user_id]
, up.plane_id
, up.fuel
, up.[status]
, sp.name AS shop_Plane_Name
, sp.fuel_capacity AS shop_Plane_Fuel_Capacity
FROM User_Planes up
INNER JOIN Shop_Planes sp ON up.plane_id = sp.id
AND up.fuel < sp.Fuel_Capacity
WHERE up.[status] = 'Ready'
AND up.[user_id] = ?
Definitely find a tutorial for JOINs, and don't use SELECT *. With SELECT *, you may end up querying much more than you actually need and it can cause problems if the table changes. You'll enjoy your day much more if you explicitly name the columns you want in your query.
I've aliased some of the columns (with AS) since some of those column names may be reserved words. I've also moved the JOIN criteria to include a filter on fuel

How to write sql query for the following tables

I have a table name as "invoice" which consists of column name "CId"
I have another table name as invoiceclient_details which consists of column name "CId"
So now my question is "what query should i write so that i will get the data of greater "CId" i.e. rows of data which consists of greater "CID"
I have tried like this
SELECT
invoiceclient_details.OrganizationName,
invoiceclient_details.InvoiceNo,
invoiceclient_details.InvoiceDate,
invoiceclient_details.DeliveryNote,
invoiceclient_details.TermsofPayment,
invoiceclient_details.EsugamNo,
invoiceclient_details.OrganizationName,
invoiceclient_details.BuyerOrderNo,
invoiceclient_details.BuyDate,
invoiceclient_details.DispatchDocumentNo,
invoiceclient_details.Dated,
invoiceclient_details.DispatchThrough,
invoiceclient_details.Destination,
invoiceclient_details.TermsofDelivery,
invoiceclient_details.BuyerTin,
invoice.id,
invoice.DescriptionOfGoods,
invoice.Quantity,
invoice.PerUnitPrice,
invoice.TotalPrice,
invoice.VAT14,
invoice.VAT5,
invoice.ServiceTax,
invoice.CST
FROM invoiceclient_details,invoice
WHERE MAX(invoiceclient_details.CId) = MAX(invoice.CId);
But it is showing an error like
"misusage of group function"
Use an INNER JOIN to join the tables on the CId.
SELECT *
FROM invoice i
INNER JOIN invoiceclient_details icd ON i.CId = icd.CId
Try this
select *
from invoice,invoiceclient_details
where
invoice.CId in (Select max(invoiceclient_details.CId) from invoiceclient_details)
and
invoiceclient_details.CId in (Select max(invoiceclient_details.CId) from invoiceclient_details)