I am using caldera forms in my WordPress site to collect data for new admissions for our club. Form functions as expected. I am trying to view a list of open applications and a page to view them. Following is my SQL table tor entries (cf_form_entries).
+----+-----------------+--------+
| ID | Form ID | Status |
+----+-----------------+--------+
| 1 | CF5852c23e56b1d | active |
+----+-----------------+--------+
| 2 | CF5852c23e56b1d | active |
+----+-----------------+--------+
| 3 | CF5852c23e56b1d | active |
+----+-----------------+--------+
Following table contains all the information submitted by the form (cf_form_entry_values);
+----+----------+---------------+--------------------+
| id | entry_id | slug | value |
+----+----------+---------------+--------------------+
| 1 | 1 | branch | Branch A |
| 2 | 1 | full_name | asdasd asdasd |
| 3 | 1 | email_address | b2196363#trbvn.com |
| 4 | 1 | phone | 111111111 |
| 5 | 2 | branch | Branch A |
| 6 | 2 | full_name | Full Name |
| 7 | 2 | email_address | asdasd#asdas.com |
| 8 | 2 | phone | 111111111 |
| 9 | 3 | branch | Branch A |
| 10 | 3 | full_name | Namwe |
| 11 | 3 | email_address | wert#wertwert.com |
| 12 | 3 | phone | 111111111 |
+----+----------+---------------+--------------------+
I can run a simple select query and get the open application details of a given branch, inner joining tables.
SELECT cf_form_entries.id,
cf_form_entries.form_id,
cf_form_entries.status,
cf_form_entry_values.slug,
cf_form_entry_values.value
FROM cf_form_entry_values
INNER JOIN cf_form_entries
ON cf_form_entry_values.entry_id = cf_form_entries.id
WHERE cf_form_entry_values.slug = 'branch'
AND cf_form_entry_values.value LIKE '%Branch A%'
Above query results in the following table;
+----+-----------------+--------+--------+----------+
| id | form_id | status | slug | value |
+----+-----------------+--------+--------+----------+
| 1 | CF5852c23e56b1d | active | branch | Branch A |
| 3 | CF5852c23e56b1d | active | branch | Branch A |
+----+-----------------+--------+--------+----------+
My question is, How can I display (echo) the other details such as the name, email address, etc. of the selected tables?
As such my end result shall display all details of the open applications in a table. (not just the branch name)
I tried a while loop. But I can only echo the branch names as they are the only data selected in my inner joined table.
One method is conditional aggregation:
SELECT fe.id, fe.form_id, fe.status,
MAX(CASE WHEN fev.slug = 'branch' THEN fev.value END) as branch,
MAX(CASE WHEN fev.slug = 'full_name' THEN fev.value END) as full_name,
. . .
FROM cf_form_entries fe INNER JOIN
cf_form_entry_values fev
ON fev.entry_id = fe.id
GROUP BY fe.id, fe.form_id, fe.status;
The nice thing about this approach is that adding a new value only requires adding a new expression in the SELECT.
Try Following Query By Using LEFT JOIN ON Two Tables.
SELECT cfev.*,cfm.Form ID as entry_id
FROM cf_form_entry_values cfev
LEFT JOIN cf_form_entries cfm ON cfm.id = cfev.entry_id
WHERE cfev .slug = 'branch' AND vfm.value LIKE '%Branch A%'
This Might Be Helpful. And You Get Proper Output...
This should give you the first two values, and you can use the same pattern for the rest:
SELECT entries.id,
entries.form_id,
entries.status,
(SELECT value FROM cf_form_entry_values as v
WHERE slug='branch' and entry_id=entries.entry_id) as branch,
(SELECT value FROM cf_form_entry_values as v
WHERE slug='full_name' and entry_id=entries.entry_id) as full_name
FROM cf_form_entry_values
INNER JOIN (
SELECT * FROM cf_form_entry_values
INNER JOIN cf_form_entries
ON cf_form_entry_values.entry_id = cf_form_entries.id
WHERE cf_form_entry_values.slug = 'branch'
AND cf_form_entry_values.value LIKE '%Branch A%'
) as entries
ON cf_form_entry_values.entry_id = entries.id
GROUP BY cf_form_entries.id
Related
I have two tables and i'm like to query 2 tables to obtain a report.
POSITION
+-------------+---------------+
| position_id | position_name |
+-------------+---------------+
| 1 | E1P1 |
| 2 | E1P2 |
| 3 | E3P3 |
| 4 | E4P4 |
+-------------+---------------+
PEOPLE
+------------+-------------+--------------------+
| people_id | people_name | people_position_id |
+------------+-------------+--------------------+
| 1 | JOHN | 2 |
| 2 | MARK | 4 |
+------------+-------------+--------------------+
QUERY
SELECT position_id, position_name, people_name FROM position
RIGHT JOIN people ON people_position_id = position_id
When I use simple query I get only matched rows, ho to obtain all?
I'm like to obtain this result
+----+----------+--------+
| ID | POSITION | STATUS |
+----+----------+--------+
| 1 | E1P1 | Empty |
| 2 | E1P2 | JOHN |
| 3 | E3P3 | Empty |
| 4 | E4P4 | MARK |
+----+----------+--------+
I would use a left join here:
SELECT
po.position_id,
po.position_name,
COALESCE(pe.people_name, 'EMPTY') AS STATUS
FROM position po
LEFT JOIN people pe
ON po.position_id = pe.people_position_id;
By the way, the reason your current right join attempt is failing is that you have placed the people table on the right side of the join. This means that non matching position records would be discarded. Here is my answer above, rewritten using a right join:
SELECT
po.position_id,
po.position_name,
COALESCE(pe.people_name, 'EMPTY') AS STATUS
FROM people pe
RIGHT JOIN position po
ON po.position_id = pe.people_position_id;
Note carefully that the table order has switched. Most of the time, you will see people using left joins rather than right joins.
I have 1 master_table and 2 sub_tables. I want the join the 3 columns together (but the problem is the 2 sub_tables do not have any column that share the same value) and then SELECT * based on 2 different columns from the 2 sub_tables.
I've searched and tried many ways of coding, but couldn't find a solution.
SELECT *
FROM (master INNER JOIN sub_1 ON master.id=sub_1.id WHERE sub_1.column_1 = 'Y')
AND (master INNER JOIN sub_2 ON master.id=sub_2.id WHERE sub_2.column_2 = 'Y')
ORDER BY master.id
++++++++++++++++++++++++++++++++++++++++++++++++++
* Finally, solved. See the solution at the bottom of this post. *
++++++++++++++++++++++++++++++++++++++++++++++++++
===========
Edit: explain more about my data, problem and MySQL code
I have 3 tables stored in MySQL as follow
Master_table: regist
------------------------------------------
| reg_no | firstname | lastname | submit |
------------------------------------------
| 1 | first_A | last_A | N |
| 2 | first_B | last_B | A |
| 3 | first_C | last_C | P |
| 4 | first_D | last_D | P |
| 5 | first_E | last_E | A |
| 6 | first_F | last_F | N |
| 7 | first_G | last_G | N |
| 8 | first_H | last_H | A |
------------------------------------------
Sub_1: sub_A Sub_2: sub_P
------------------------------ ------------------------------
| reg_no | A_title | reply_A | | reg_no | P_title | reply_P |
------------------------------ ------------------------------
| 2 | 222 | Y | | 3 | 333 | N |
| 5 | 555 | N | | 4 | 444 | Y |
| 8 | 888 | Y | ------------------------------
------------------------------
I want to create a query that gives result like this
----------------------------------------------------------------------------------
| reg_no | firstname | lastname | submit | A_title | reply_A | P_title | reply_P |
----------------------------------------------------------------------------------
| 2 | first_B | last_B | A | 222 | Y | | |
| 8 | first_H | last_H | A | 888 | Y | | |
| 4 | first_D | last_D | P | | | 444 | Y |
----------------------------------------------------------------------------------
or
-----------------------------------------------------------
| reg_no | firstname | lastname | submit | title | reply |
-----------------------------------------------------------
| 2 | first_B | last_B | A | 222 | Y |
| 8 | first_H | last_H | A | 888 | Y |
| 4 | first_D | last_D | P | 444 | Y |
-----------------------------------------------------------
$sql = "SELECT *
FROM (regist INNER JOIN sub_A ON regist.reg_no = sub_A.reg_no WHERE sub_A.reply_A = 'Y')
AND (regist INNER JOIN sub_P ON regist.reg_no = sub_P.reg_no WHERE sub_P.reply_P = 'Y')
ORDER BY regist.reg_no";
Expected outcome:
ECHO personal data of all registrants who got reply as 'Y'
if($row['submit']=="A") $title = $row['A_title'];
elseif($row['submit']=="P") $title = $row['P_title'];
$result = mysql_query($sql) or die(mysql_error());
while($row = mysql_fetch_array($result))
{
echo $row['reg_no']." / ".$row['firstname']." ".$row['lastname']." / ".$title."<br>";
}
Problem: my SELECT code resulted in error. The code from #GMB and #Rogue didn't error, but echo give nothing.
If it is not possible to code a query as I want, I will just modify the column names (sub_1.reply_A and sub_2.reply_P) to be the same and change the input code in other webpages. However, it would be best if there is a way because I don't know whether the 'reply' columns were used somewhere else.
========================
Solution: a little modification from #Rogue code
SELECT *
FROM master
LEFT OUTER JOIN sub_1
ON master.id=sub_1.id
LEFT OUTER JOIN sub_2
ON master.id=sub_2.id
WHERE sub_1.column_1 = 'Y'
OR sub_2.column_2 = 'Y'
ORDER BY master.id
Do you just want simple JOINs between these 3 tables ?
SELECT m.*, s1.*, s2.*
FROM master m
INNER JOIN sub_1 s1 ON m.id=s1.id AND s1.column_1 = 'Y'
INNER JOIN sub_2 s2 ON m.id=s2.id AND s2.column_2 = 'Y'
ORDER BY m.id;
If you have master records that may not exist in both sub tables, you can switch to LEFT JOIN to avoid filtering them out.
Guidelines :
typical syntax is SELECT ... FROM table1 INNER JOIN table2 ON ... INNER JOIN table3 ON...
better put all conditions related to a JOINed table in the ON clause of the join rather than in the WHERE clause
avoid SELECT * : be specific about the columns you want to select
use table aliases to make the query easier to read
You're a little off syntactically:
SELECT *
FROM master
LEFT OUTER JOIN sub_1
ON master.id=sub_1.id
LEFT OUTER JOIN sub_2
ON master.id=sub_2.id
WHERE sub_1.column_1 = 'Y'
AND sub_2.column_2 = 'Y'
ORDER BY master.id
Personally I would recommend not using SELECT * and only grabbing the data you will need. As for determining what join to use, I like to link to CodingHorror's blog post in these times.
Edit: swapped INNER to LEFT OUTER, per OP's update
I am working on a project to catalogue laptops and as such am trying to re-use as much information as possible. A simplified version of the MySQL tables are:
Table: laptop
|----------------------------------|
| id | make | line | model |
| 1 | 1 | 1 | Late 2015 13" |
|----------------------------------|
Table: make
|----------------------------------|
| id | name | other info |
| 1 | Apple | |
|----------------------------------|
Table: line
|----------------------------------|
| id | name | other info |
| 1 | MacBook Pro | |
|----------------------------------|
Table: networking
|----------------------------------|
| id | name | other info |
| 1 | A wifi card | |
| 2 | Another card | |
| 3 | Yet another | |
|----------------------------------|
Table: laptop_networking
|----------------------------------|
| id | networking | laptop |
| 1 | 3 | 1 |
| 2 | 1 | 1 |
|----------------------------------|
So far I used the current statement to retrieve the data in PHP
$statement = $dbc->prepare("
SELECT l.id
, m.id AS makeID
, m.name AS makeName
, n.id AS lineID
, n.name AS lineName
, l.model
FROM laptop l
JOIN make m
ON l.make = m.id
JOIN line n
ON l.line = n.id
WHERE l.id = :laptop);
$statement->bindParam(':laptop', $anID, PDO::PARAM_INT);
$statement->execute();
$theLaptop = $statement0>fetch();
At present running this code with $anID = 1 returns
|---------------------------------------------------------------|
| id | makeID | makeName | lineID | lineName | Model |
| 1 | 1 | Apple | 1 | MacBook Pro | Late 2015 13" |
|---------------------------------------------------------------|
What I would like to do is append another column to the table which returns all names from Networking which have an ID equal to a row in laptop_networking where the laptop field is equal to the ID from the retrieved laptop row
Such as:
|------------------------------------------------------------------------------------------|
| id | makeID | makeName | lineID | lineName | model | networking |
| 1 | 1 | Apple | 1 | MacBook Pro | Late 2015 13" | Yet another, A wifi card |
|------------------------------------------------------------------------------------------|
Is this possible as my many attempts at different types of JOINs have not yielded the desired results.
Thank you
Try this query:
SELECT laptop.id,
make.id AS makeID,
make.name AS makeName,
line.id AS lineID,
line.name AS lineName,
laptop.model,
t.networking
FROM laptop
INNER JOIN make
ON laptop.make = make.id
INNER JOIN line
ON laptop.line = line.id
INNER JOIN
(
SELECT t1.laptop, GROUP_CONCAT(t2.name) AS networking
FROM laptop_networking t1
INNER JOIN networking t2
ON t1.networking = t2.id
GROUP BY t1.laptop
) t
ON laptop.id = t.laptop
WHERE laptop.id = :laptop
Demo here:
Rextester
I have three tables group_sentences, group_sentences_attributes and group_senteces_categories.
I have an attributes array which I am using in query with IN (after implode).
Then I have one category ID because they are stored recursively, so no need for an array.
I need to select one group number where is the biggest match for $attributesArray and of course category too.
Here is table group_sentences_attributes
+-----+-------+-----------+
| id | group | attribute |
+-----+-------+-----------+
| 1 | 1 | 3564 |
| 2 | 1 | 3687 |
| 3 | 1 | 3689 |
| 4 | 2 | 3687 |
| 5 | 2 | 3564 |
+-----+-------+-----------+
Here is group_sentences_category
+-----+-------+----------+
| id | group | category |
+-----+-------+----------+
| 1 | 1 | 1564 |
| 2 | 1 | 1221 |
| 3 | 1 | 1756 |
| 4 | 2 | 1358 |
| 5 | 2 | 1125 |
+-----+-------+----------+
Here is my query, but I am afraid that it won't do the job done.
SELECT group_categories.group
FROM group_categories, group_attributes
WHERE group_categories.category = '$category'
AND group_attributes.attribute IN ($attributesArray)
GROUP BY group_categories.group
ORDER BY count(group_attributes.attribute)
Any help would be appreciated, thanks.
First, the table in your query do not match the tables in the question. I am guessing they are simply missing the "sentence". Then, you have no join clause. Simple rule: Never use commas in the from clause.
group is a lousy name for a column, because it is a keyword in SQL. The following may be what you are looking for:
SELECT gc.groupid
FROM group_sentences_attributes sa JOIN
group_sentences_category sc
ON sa.groupid = sc.groupid
WHERE sc.category = '$category' AND
sa.attribute IN ($attributesArray)
GROUP BY sa.groupid
ORDER BY count(sa.attribute);
If you only want one row, then add LIMIT 1 to the end.
I am trying to get some statistics for an online game I maintain. I am searching for an SQL statement to get the result on the bottom.
There are three tables:
A table with teams, each having a unique identifier.
table teams
---------------------
| teamid | teamname |
|--------|----------|
| 1 | team_a |
| 2 | team_x |
---------------------
A table with players, each having a unique identifier and optionally an affiliation to one team by it's unique teamid.
table players
--------------------------------
| playerid | teamid | username |
|----------|--------|----------|
| 1 | 1 | user_a |
| 2 | | user_b |
| 3 | 2 | user_c |
| 4 | 2 | user_d |
| 5 | 1 | user_e |
--------------------------------
Finally a table with events. The event (duration in seconds) is related to one of the players through their playerid.
table events.
-----------------------
| playerid | duration |
|----------|----------|
| 1 | 2 |
| 2 | 5 |
| 3 | 3 |
| 4 | 8 |
| 5 | 12 |
| 3 | 4 |
-----------------------
I am trying to get a result where the durations of all team members is summed up.
result
--------------------------
| teamid | SUM(duration) |
|--------|---------------|
| 1 | 14 | (2+12)
| 2 | 15 | (3+8+4)
--------------------------
I tried several combinations of UNION, WHERE IN, JOIN and GROUP but could not get it right. I am using PostgreSQL and PHP. Can anyone help me?
Just use sum with group by:
select t.teamid, sum(e.duration)
from team t
join players p on t.teamid = p.teamid
join events e on p.playerid = e.playerid
group by t.teamid
If you need all teams to be returned even if they don't have events, then use an outer join instead.
Try this
SELECT teamid, Sum(duration),
AS LineItemAmount, AccountDescription
FROM teams
JOIN teams ON teams.teamid = players.teamid
JOIN events ON players.playersid = events.playersid
JOIN GLAccounts ON InvoiceLineItems.AccountNo = GLAccounts.AccountNo
GROUP BY teamid
http://www.w3computing.com/sqlserver/inner-joins-join-two-tables/