Query different table when column exist - mysql

Database: MySql 5.5.3
I have a type column in table topic, if the type is 'E' which means there is an entry exist in 'Event' Table and it should query "TOPIC_HAS_EVENT" table to get few more colums from the EVENT Table. In the same way if Type is 'P' which means there is an entry exist in 'Poll Table' and it should query "TOPIC_HAS_POLL" table to get few columns from POLL Table. If the type is null then it should query as usual to get all the rows and their comments from the comment table.
The end results should have all the topics rows of all types ('E','P', NULL) and their specific columns from other table. If that can accomplish easily then i need to add few more columns as mentioned below
More complex
If type='E' have some rows, it should get some more rows such as user information from EVENT_HAS_USER table.
Relationship
Each Topic has Many Comments
Each Topic has One Event
Each Topic has One Poll
EVENT ManyTOMany User
Query so far created. I still need to add 'type' column. Please help me with it.
SELECT DISTINCT
T.TOPIC_GUID, COUNT(*) TOTAL_COMMENTS
FROM
CIRCLE C, CIRCLE_HAS_USER CHU, CIRCLE_HAS_TOPIC CHT, TOPIC T
LEFT JOIN TOPIC_COMMENT TC ON T.TOPIC_GUID = TC.TOPIC_GUID
WHERE
CHT.CIRCLE_GUID = C.CIRCLE_GUID
AND T.TOPIC_GUID < 400000 -- ?
AND CHT.TOPIC_GUID = T.TOPIC_GUID
AND CHU.CIRCLE_GUID = C.CIRCLE_GUID
AND CHU.USER_GUID = 1
AND CHU.STATUS = 'A'
GROUP BY T.TOPIC_GUID
ORDER BY T.LAST_UPDATED_TIMESTAMP DESC
LIMIT 10

Try this:
select (case when type = 'type1' then (select field from table1) else (select field from table2) end) as a from table;

Related

Why does my nested SQL SELECT returns either null or 'more than one row'?

I went through similar questions here, but no solution given there works for me.
The idea is that I need to move data from old_database's OldDoc to new_database's NewDoc. The majority of the columns match, but there are two exceptions.
Namely, USER_ID column needs to be filled with an ID extracted from new_database's User table. What ID should be given to a record is decided by comparing old_database's OldDoc's operator column (it contains just the name of the user) to a name within new_database's User table which contains names and IDs.
So if old_database's OldDoc's operator column contains a row 'Nezuko-chan' and new_database's User table has Name column saying 'Nezuko-chan' and ID column saying '666', then new_database's NewDoc's USER_ID column should be given '666' here.
Basically the same logic applies to LOCATION_ID -> there's a Location table in new_database with Name and ID and, by comparing old_database's OldDoc's lokalizacja column (with just a name) to new_database's Location's Name column, I want to extract new_database' Location's ID for that name.
Below code...
INSERT INTO new_database.NewDoc (ID, NR_DOC, NR_HANDLE, DOC_DATE, PLANNING_RELEASE, QUANTITY, CASES, VOLUME, ZAPIS, USER_ID, LOCATION_ID, TYPE_ID)
SELECT
ol.id,
ol.nrWZ,
ol.nrHandle,
ol.dataWZ,
ol.planowaneWydanie,
ol.qty,
ol.cart,
ol.volume,
ol.Zapis,
(SELECT u.ID FROM new_database.User u WHERE u.NAME = ol.operator),
(SELECT loc.ID FROM new_database.Location loc WHERE loc.NAME = ol.lokalizacja),
1
FROM old_database.OldDoc ol
... results in this festival of errors:
Column 'USER_ID' cannot be null
Column 'LOCATION_ID' cannot be null
Subquery returns more than 1 row
Column 'USER_ID' cannot be null
Column 'LOCATION_ID' cannot be null
Subquery returns more than 1 row
Column 'USER_ID' cannot be null
Column 'LOCATION_ID' cannot be null
Subquery returns more than 1 row
Column 'USER_ID' cannot be null
Column 'LOCATION_ID' cannot be null
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.id,
ol.nrWZ,
ol.nrHandle,
ol.dataWZ,
ol.planowaneWydanie,
ol.qty,
...' at line 3
I also tried replacing the syntax of my nested SELECTs with the below...
(SELECT u.ID FROM new_database.User u, old_database.OldDoc omg WHERE u.NAME = omg.operator),
(SELECT loc.ID FROM new_database.Location loc, old_database.OldDoc omg WHERE loc.NAME = omg.lokalizacja)
... which changes nothing.
This needs to be a mistake on my part as none of the columns I am trying to reach for is empty. Data is everywhere (checked by independent SELECTs).
I suppose the problem lies with my nested SELECTs which return "lists of results" instead of a single result for every row. Again, I checked similar questions before and can't find answers there so I must be making a very... individual kind of a mistake.
Thank you in advance for your time.
Kind Regards,
Bartek
Use INSERT .. SELECT with proper joining:
INSERT INTO new_database.NewDoc (
ID, NR_DOC, NR_HANDLE, DOC_DATE,
PLANNING_RELEASE, QUANTITY, CASES, VOLUME,
ZAPIS, USER_ID, LOCATION_ID, TYPE_ID
)
SELECT ol.id, ol.nrWZ, ol.nrHandle, ol.dataWZ,
ol.planowaneWydanie, ol.qty, ol.cart, ol.volume,
ol.Zapis, u.ID, loc.ID, 1
FROM old_database.OldDoc ol
JOIN new_database.User u ON u.NAME = ol.operator
JOIN new_database.Location loc ON loc.NAME = ol.lokalizacja;
Maybe LEFT JOIN needed (if some row have no according value in User or Location).
Of course NAME in both ref. tables must be unique.
For "column .. cannot be NULL" - alter table definition and add correct DEFAULT value to each column mentioned in the errors list.

Unable to create a temporary table from a select query with multiple joins. Throws 'Duplicate column name 'id'

This is the query that is causing the problem:
CREATE TEMPORARY TABLE fetchedCropVariety ENGINE = MEMORY
SELECT *
, hz.zoneName
, i.fullImageUrl
, i.previewImageUrl
, u.userName
FROM seedrecord s
LEFT
JOIN HardinessZone hz
ON hz.id = s.hardiness_zone_id
JOIN image i
ON s.id = i.seedrecord_id
JOIN members u
ON s.FK_USER = u.id
WHERE s.id = 1
AND s.deleted = FALSE;
When i execute this query it throws the error Error Code: 1060. Duplicate column name 'id'
There are no duplicate columns named id in the table seedrecord so this is caused by one or more id columns from the other tables that are only used to join them in order to retrieve zoneName and fullImageUrl.
When i remove *, from the query the query does run but all the fields from seedrecord are omitted. It must be the id column from seedrecord that is clashing somehow with the id columns from hardinessZone and members but I am not trying to include the id fields of those 2 tables into the temporary table i want to create so this error is really puzzeling me.
Can anyone tell me what i can do to stop this error from occurring?
Thank you
don't make
select *
It will take all clomuns that you have in your From Clause
And you have the at least two Columns that are namend id
MAke instead
S.*,u.*
and so on

return values of table 1 based on single column in table 2

I have 3 tables that I am using and need to make a query to return data from one table based on the value of a single column in the second table.
tbl_user
ID
login
pass
active
mscID
tbl_master
ID
name
training_date
MSCUnit
Active
tbl_msc
mscID
mscName
my current SQL statement:
SELECT
tbl_master.ID,
tbl_master.name,
tbl_master.training_date,
tbl_master.MSCUnit,
tbl_master.active,
tbl_user.mscID
FROM
tbl_master,
tbl_user
WHERE
tbl_master.active = 1 AND tbl_master.MSCUnit = tbl_user.mscID
The values stored in tbl_msc.mscID is a varchar(11) and it contains a string similar to A00 or A19. This is also the Primary key in the table.
The values stored in tbl_user.mscID matches that of tbl_msc.mscID. The values stored in tbl_master.UnitMSC also matches that of tbl_msc.mscID.
My goal is to return all records from tbl_master where the currently logged in user has the same mscID. The problem I am having is the statement returns all records in tbl_master.
I have tried several different join statements and for some reason, I cannot get this to filter correctly.
I am missing something. Any assistance in the SQL statement would be appreciated.
Thanks,
Will
You should be writing this using joins. I don't know how you know who the current user is, but the idea is to join the three tables together:
SELECT m.ID, m.name, m.training_date, m.MSCUnit, m.active,
u.mscID
FROM tbl_master m JOIN
tbl_user u
ON m.MSCUnit = u.mscID JOIN
tbl_msc msc
ON msc.mscID = u.msc_ID
WHERE m.active = 1 AND msc.mscName = ?;
Notice the use of proper, explicit, standard JOIN syntax and table aliases.
Select a.*, b.userid from
table_master a, table_user b where
a.mscunit in (select mscid from
table_user where active=1)
This should point you in the right direction.

Unknown column 'wp_cons_users.id' in 'on clause'

I have three table one is for users and other one is for subject and third one contain user_id, subject_id foreign keys.
I get unknow coloumn when I run the following sql.
SELECT wp_cons_users.first_name, wp_cons_subject.subject, wp_cons_skilllist.skill_level
FROM `wp_cons_subject`
JOIN wp_cons_skilllist ON wp_cons_skilllist.user_id = wp_cons_users.id
JOIN wp_cons_users ON wp_cons_users.id = wp_cons_skilllist.user_id
WHERE wp_cons_subject.id = '1'
ORDER BY `wp_cons_skilllist`.`skill_level` DESC
I can't find the error with this query.
wp_cons_skilllist
column link to
id (primay)
user_id wp_cons_users -> id
subj_id wp_cons_subject -> id
skill_level
Here I try to get the username, skill level and subject for any given subject id.
Looks like your main problem is with the ordering of your JOINs. In your first join, you are matching with wp_cons_users.id, but you don't join that table until later in the query. If you re-order the joins it should work better. Also, based on your table description, it seems that you will also need to join on subject_id. This query should help:
SELECT wp_cons_users.first_name
, wp_cons_subject.subject
, wp_cons_skilllist.skill_level
FROM wp_cons_users
JOIN `wp_cons_subject`
ON wp_cons_users.id=`wp_cons_subject`.user_id
AND wp_cons_subject.id = '1'
JOIN
wp_cons_skilllist
ON wp_cons_skilllist.user_id = wp_cons_users.id
AND wp_cons_skilllist.subject_id = `wp_cons_subject`.id
ORDER BY `wp_cons_skilllist`.`skill_level` DESC
I am guessing about the field names that weren't in your original query, so you may have to make some changes if they're different from what I'm assuming.
Without information about your attributes in your table, I'm afraid we can only assume that there is no ID column in your wp_cons_users table.
when I corrected the query to following it started to work.
SELECT wp_cons_users.first_name, wp_cons_subject.subject, wp_cons_skilllist.skill_level
FROM `wp_cons_skilllist`
JOIN wp_cons_subject ON wp_cons_subject.id = wp_cons_skilllist.subject_id
JOIN wp_cons_users ON wp_cons_users.id = wp_cons_skilllist.user_id
WHERE wp_cons_skilllist.subject_id = '1'
ORDER BY `wp_cons_skilllist`.`skill_level` DESC
LIMIT 0 , 30

Mysql, search in multiple tables

I'm working on an async game, but I'm totally new to MySQL and PHP. I have two tables, tb_users and tb_matches. The first one stores all users and their status (for example, a value of 0 in the 'status' column means the player is in stand-by, while a value of 1 means the player is waiting for an opponent to play a match).
The tb_matches table stores all the matches, both active and inactive (completed) ones. There are two columns in this table with player IDs.
What I am trying to do is to perform a search for an available opponent, which must fulfill these requirements:
1) it must have a status of 1 in the tb_users table
2) it must not already have an active match with the user searching for a new opponent
I've tried with:
SELECT *
FROM tb_users
JOIN tb_matches
WHERE tb_users.status = "1"
AND tb_matches.player1 != '".$username."'
AND tb_matches.player2 != '".$username."'
..but it's not giving me any result. Also, it should take into account that in the tb_matches table, there could be no matches at all.
Any help? Also, is there a better way to accomplish this task?
Consider the following alternate table structure:
tb_users
---------
id
name
seeking
tb_user_matches
---------------
match_id
player_id
tb_matches
----------
id
started
ended
status
Adding a third (many-to-many) table to store which players are involved in which match allows simpler queries, see below.
Change "status" in tb_users to "seeking" so a boolean data type makes sense.
Don't store player names in tb_matches, store their ID. (Allows name changes without breaking links (Normalization).)
Consider adding datetime fields to tb_matches to store the match start and end date; it might be useful in the future.
The "status" column in tb_matches can indicate three match statuses: waiting for more players, in progress, or completed (see below).
With this structure, you can use the following query to find players that are:
Searching for a match (seeking = 1)
Not already in a match that is waiting for players
SELECT u.id, u.name
FROM tb_users u
LEFT JOIN tb_user_matches um
JOIN tb_matches m
ON um.match_id = m.id AND m.status = 0
ON u.id = um.player_id
WHERE u.seeking = 1
AND um.match_id IS NULL;
I am proposing tb_matches.status could be "0" for inactive (waiting for players), "1" for active, and "2" for completed.
This does not necessarily check if the player is already engaged in an active match. Perhaps your game allows players to participate in multiple simultaneous matches? If not, you can alter the query to exclude matches that are active as well (change m.status = 0 to m.status != 2).
Edit:
To explain the query in English (as best I can):
Select user id and name from the users table. Include matches that the user is involved where the match status is "0" (waiting). (The LEFT JOIN makes it so if the user is not involved in any matches with status "0", the match_id will be empty (null).)
Now, from this set of data, only show users that are seeking (u.seeking = 1), and aren't in a waiting match (um.match_id IS NULL).
Try this (note that you will have to substitute 'username' for the actual user name)
SELECT *
FROM tb_users
WHERE Username != 'username'
AND status = 1
AND NOT EXISTS (SELECT *
FROM tb_matches
WHERE (player1 = 'username' OR player2 = 'username')
AND Status = 'inactive')
SELECT *
FROM
`tb_users`
WHERE
`tb_users`.`status` = "1"
AND
`tb_users`.`name` NOT IN (
SELECT `player1` FROM `tb_matches` WHERE `player2` = 'username'
UNION
SELECT `player2` FROM `tb_matches` WHERE `player1` = 'username'
UNION
SELECT 'username'
)