JOIN single attribute with multiple table and merge result - php

I would join my table notifications with 2 different tables, let me present a similar example.
Notifications:
ID | player_id | item_id | ....
Basket player's items
player_id | item_id | note | points | rebounds
Soccer player's items
player_id | item_id | note | match | goal
IMPORTANT: all the player ids are unique, the soccer players are in the format 1******** and the basket players are in the format 5********. so also all the couples player_id - item_id are unique.
The result should be a table like this:
id | player_id | item_id | note | attr1 | attr2
where in "note" there is a note of both kind of players and "attr1" is filled by points or match depends on the player type (same type. INT)
Moreover, the items can be joined with tables SOCCER_ITEMS and BASKET_ITEMS where there are information about the item itself. This JOIN can create duplicated rows because the item_id is not unique between the 2 tables and so a basket item can be joined with the info of a soccer item, creating issues.
is it possible to collect data in the way presented in SQL? I'm writing the code in PHP (don't know if it is useful or not)

You can use the function COALESCE():
SELECT n.id, n.player_id, n.item_id,
COALESCE(s.note, b.note) note,
COALESCE(s.match, b.points) attr1,
COALESCE(s.goal, b.rebounds) attr2
FROM notifications n
LEFT JOIN soccer s ON s.player_id = n.player_id AND s.item_id = n.item_id
LEFT JOIN basket b ON b.player_id = n.player_id AND b.item_id = n.item_id

Related

I am working On SQL query but not working full outer join

I want to work on SQL. inner join is not working missing. I am using two tables get data on "city_id " field these table code so please help me
inventory
==========================================
inventory_id | city_id | title |is_enabled
==========================================
1 | 1 | abc | 1
2 | 1 | bcd | 1
cities
====================================
city_id | city | title
===================================
1 | delhi | abc
2 | nodia | bcd
SELECT * FROM inventory i
INNER JOIN cities c
ON i.city_id = c.city_id
WHERE i.is_enabled = 1
ORDER BY i.inventory_id DESC LIMIT 10;
Some databases (such as MS Access and MySQL) do not support FULL OUTER JOIN.
However, FULL OUTER JOIN is rarely needed -- and almost never when you are using keys defined between tables. Well structured databases have keys with appropriate values.
I suspect an INNER JOIN does what you want:
SELECT . . . -- list out the columns you want
FROM inventory i INNER JOIN
cities c
ON i.city_id = c.city_id
WHERE i.is_enabled = 1
ORDER BY i.inventory_id DESC
LIMIT 10;
This query assumes that the inventory rows have a valid city_id. If some are NULL (an allowed, non-matching value), you can use LEFT JOIN instead.
Some other notes:
List out the columns you want explicitly. In particular, duplicate column names can be problematic.
Use table aliases, so the query is easier to write and to read.
Qualify all column names. I'm guessing that is_enabled comes from inventory. I should not have to guess.
Do not put single quotes around numeric constants. I am guessing that is_enabled is a number, not a string.

Left Join and SUM on two tables, MYSQL

I have a table that contains information about an item, and another table that references the owner of that item, like so:
baseItem
--------
itemID | 1 | 2 | 3 | 4 |
itemSize | 5 | 1 | 5 | 3 |
itemCost | 100 | 50 | 1 | 99 |
itemOwner
--------
ownerID | 1 | 1 | 3
itemID | 1 | 4 | 2
What I'm after are the SUMS of itemSize and itemCOST based on the owner. I've looked around but none of the answers I've seen make sense? Here's the best I could come up with, which clearly isn't working:
SUM itemCost FROM baseItem.itemCost LEFT JOIN itemID ON itemOwner.itemid = baseItem.itemid
SELECT ownerId, sum(itemCost) as OwnerCost, sum(itemSize) as OwnerSize
FROM itemOwner
LEFT JOIN baseItem
ON itemOwner.itemid = baseItem.itemid
GROUP BY ownerId
A SELECT statement lists which fields you want to read from the table; in this case you want two values: the id of the owner, and the sum of the values of the items they own. However, since you're using sum (an aggregate function), you must GROUP your elements over some parameter. In this case, you want to group them by ownerId.
A FROM clause references a table; you can start with either baseItem or itemOwner, it makes no difference in this case. You can think of LEFT JOIN as a cartesian product that creates a new table, which contains every element from the cartesian product of both, filtered by the ON clause. However will always have all the items in the left table which is itemOwner and when there are no matching rows in the baseItem all the fields will be NULL. The SUM function will act as if those are 0s and should return you a 0 sum for non matching rows in the baseItem table.
Maybe it is not working because it is invalid SQL statement. Try following code
SELECT SUM(baseItem.itemCost) FROM baseItem
LEFT JOIN itemOwner ON itemOwner.itemId = baseItem.itemId

How to store multiple rows values in single table with single id

I want to save multiple rows with single id store in table. What should I do? Please guide me.
For example:
| table1 |
|-----------------|
|id |name |
|001(pk) |Ajit |
| table2 |
|-----------------|
|id(FK) |address |
|001 |Pune |
|001 |Mumbai. |
means TWO TABLES are their in table1 id is primary key & table2 id is foreign key
i.e.: 001 id should multiple address it would be save into table2 but id must be same,
i.e.: address textbox will generate at runtime
Put its(id) default value as "001"(you deserve it) using mysql query and then while inserting a new entry leave that column to add as new.
If you're wanting to link the data in the two tables (i.e. a users table and an addresses table) just use a foreign key.
Your users table:
id | name
================
1 | Martin Bean
Your addresses table:
id | user_id | address
==================================
1 1 Newcastle upon Tyne
This way, the primary key of your addresses table is not dependent on the ID of the users table. And your query to fetch both pieces of data is easy with a join:
SELECT
u.id,
u.name,
a.address
FROM
users u
LEFT JOIN
addresses a ON u.id = a.user_id

Using a MySQL join

A user can have two types of relationships on my website. Following or Friends. I want to populate each user's news feed with the posts from users they have a relationship with. So far I have this join:
SELECT *
FROM posts a
LEFT JOIN relationships b
ON a.user_id = b.user_2
WHERE b.user_1 = $user_id AND
b.status IN (1,3,4) OR a.user_id = $user_id
ORDER BY a.post_id DESC
b.status is the column from my relationships table that determines the status of the relationship between two users. 1 being following, 3 being friends, 4 being following with a pending friend request. My join works well, except that It it doesn't take into consideration that there is only one row in my 'relationships' table that can represent a friend ship between any two people. There are two rows for following. The first being user 1(mark) following user 2(matt) and user 2(matt) following user 1(mark). But with friendships it is either a row stating one way or the other, with a status of 3. First off, is that smart practice? Or should I have two rows for this type pf relationship as well? Secondly, how can I make my JOIN QUERY also grab posts from users with where there is a relationship between user_1 and user_2 and the status = 3? With no regard to the order user_1 and user_2 are in?
Table Structure:
Posts:
| user_id | post_id | story |
-----------------------------
| 1 | 1 | text. |
-----------------------------
Relationships:
| rel_id | user_1 | user_2| status |
--------------------------------------
| 1 | 1 | 2 | 3 |
--------------------------------------
In your WHERE statement, do something like this so you match either column in the relationship table. The OR gets both of them.
WHERE b.user_1 = $user_id OR b.user_2 = $user_id
Good luck!

MySQL inner join on two columns

I have two tables, books and authors. books has a author_id column and a secondary_author_id column (no books have more than two authors). I'm so far doing:
SELECT * FROM books
LEFT JOIN authors
ON books.author_id=authors.id
which is handling the join with the first author. I can't work out how I'd handle the secondary author though. Should I change my schema, or do I just need a bit of SQL help?
SELECT books.*, author1.*, author2.*
FROM books
LEFT JOIN author AS author1
ON author1.author_id = books.author_id
LEFT JOIN author AS author2
ON author2.author_id = books.secondary_author_id
In SQL, you can alias the tables by adding it after the table name. Just be careful, now you'll have duplicate columns, so instead of author1.* you will probably want to alias the results of both author1 and author2.
EDIT
Additional details -- Say you have your basic table (i'll include the details so if people want to test on their own they can):
CREATE DATABASE test;
USE test;
CREATE TABLE books
(
book_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50),
author_id INT NOT NULL,
secondary_author_id INT
);
CREATE TABLE authors
(
author_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50)
);
INSERT INTO authors (author_id,name) VALUES (1,'Sue Z. Que'),(2,'John Doe'),(3,'Bob Smith');
INSERT INTO books (book_id,title,author_id,secondary_author_id) VALUES (1,'JOIN-ing Two Tables',1,2);
If you do the select I mention above, your result will be the following:
|----------------------- books TABLE -----------------------------|---- authors table -----|---- authors table ---|
+---------+---------------------+-----------+---------------------+-----------+------------+-----------+----------+
| book_id | title | author_id | secondary_author_id | author_id | name | author_id | name |
+---------+---------------------+-----------+---------------------+-----------+------------+-----------+----------+
| 1 | JOIN-ing Two Tables | 1 | 2 | 1 | Sue Z. Que | 2 | John Doe |
+---------+---------------------+-----------+---------------------+-----------+------------+-----------+----------+
(I've added the top header just for calrity's sake) you see you have two author_id's and two name's (as they are joins of the same table and same column names). BUT, if you alias the columns from the joins like so:
SELECT books.*, author1.name AS primary_author, author2.name AS secondary_author
FROM books
LEFT JOIN authors AS author1
ON author1.author_id = books.author_id
LEFT JOIN authors AS author2
ON author2.author_id = books.secondary_author_id;
You get a much cleaner result:
|----------------------- books TABLE -----------------------------| authors table -|- authors table --|
+---------+---------------------+-----------+---------------------+----------------+------------------+
| book_id | title | author_id | secondary_author_id | primary_author | secondary_author |
+---------+---------------------+-----------+---------------------+----------------+------------------+
| 1 | JOIN-ing Two Tables | 1 | 2 | Sue Z. Que | John Doe |
+---------+---------------------+-----------+---------------------+----------------+------------------+
SELECT books.* FROM books, authors.name, secondary_authors.name
LEFT JOIN authors
ON books.author_id=authors.id
LEFT JOIN authors as secondary_authors
ON books.secondary_author_id=secondary_authors.id
You need to rethink your design, because one day there will be a book with three authors, and the next day there will be a book with zero. (I've been there myself.)
Edit
As your comment says: yes, you need a books_authors table. As long as you have your indexes set up properly, it's not a big performance hit.
The most annoying part is that you're often going to want to string the authors together (one entry per book, concatenating all the authors into a single column). You'll probably end up creating a view for that.
just do another join on the secondary id

Categories