select count with union table sql query - php

I am making a search paging, i have tried to select count from three table using union but am getting error like this
Fatal error: Cannot pass parameter 2 by reference in /home/plooks/public_html/user/test.php on line 106here is my table structure
table 1 name >> blogpost
| bid | title | body | author |
|----- |------- |------------- |-------- |
| 1 | new | hello new | you |
| 2 | cast | broadcast | me |
| 3 | hack | who hack us | you |
table2 name >> forumnew
| fid | ftitle | fbody | user |
|----- |------- |------------- |-------- |
| 1 | new forum | hello new | you |
| 2 | cast me | broadcast | me |
| 3 | hack you | who hack him | us |
table3 name >> download
| did | file | disc | type |
|----- |------- |------------- |-------- |
| 1 | whoweare | hello new | php |
| 2 | cast | broadcast | html |
| 3 | hack | who hack us | c++ |
SQL QUERY
SELECT COUNT(id) FROM (
SELECT 'post' AS type, BID AS id FROM blogpost
UNION
SELECT 'jail' AS type, jid AS id FROM forumnew
UNION
SELECT 'article' AS type, TID AS id FROM download
)csl WHERE title LIKE :search OR title LIKE :search")

There is a mistake in the query, you don't have the title in the temporary table csl, so it cannot be used in the WHERE clause. Also the second OR title LIKE :search is superfluous. If you don't want to do a distinct count of the id, then you don't need the other columnns, only the title column to filter by, the result will be the same.
SELECT COUNT(*) FROM (
SELECT title FROM blogpost
UNION
SELECT ftitle AS title FROM forumnew
UNION
SELECT disc AS title FROM download
) csl WHERE title LIKE :search
or
SELECT
(SELECT COUNT(*) FROM blogpost WHERE title LIKE :search) +
(SELECT COUNT(*) FROM forumnew WHERE ftitle LIKE :search) +
(SELECT COUNT(*) FROM download WHERE disc LIKE :search)

Related

MySQL breaking a large table into smalller related tables

Is it possible to break a large MySQL table into smaller related tables?
for instance imagine the table:
x_data--
id | offer_price | offer_text | free_gift | free_gift_category | model_name | model_description | tariff_name | tariff_rental | tariff_minutes | tariff_texts | tariff_data | retailer_name | retailer_description
is it possible to split this out into separate tables and build relationships so the resulting tables look like:
offers--
id | offer_price | offer_text | free_gift_id | model_id | tariff_id | retailer_id
free_gifts--
id | free_gift | free_gift_category_id
free_gift_categories--
id | free_gift_category
models--
id | name | description
tariffs--
id | name | rental | minutes | texts | data
retailers--
id | name | description
i.e can I do an insert on a sub select or join?
something like:
$query = "INSERT INTO retailers (name,description)
(SELECT retailer_name, retailer_description FROM x_data) as retailer,
(SELECT MAX(id) as retailer_id FROM retailers) as retailer_id,
INSERT INTO tariffs (name, rental, minutes, texts, data) as tariffs, ...."
if this is possible how would I go about it?

Display rows based on sql results

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

How to get result from two different table with one single input

I have two different tables with different column name
Table 1 users
+-----+----------+---------+---------+------------+
| id | name | username| image | email |
+-----+----------+---------+---------+------------+
| 1 | John1 | exmple1 | img1 |a#gmail.com |
| 2 | John2 | exmple2 | img2 |b#gmail.com |
| 3 | John3 | exmple3 | img3 |c#gmail.com |
| 4 | John4 | exmple4 | img4 |d#gmail.com |
+-----+----------+---------+---------+------------+
Table 2nd Company
+-----+----------+------------+---------=------+-----------+
| id |company_name | username| description | founded |
+-----+-------------+---------+----------------+-----------|
| 1 | john1 | exmple1 |description1 | 2016 |
| 2 |CompanyName2 | exmple2 |description2 | 2016 |
| 3 |CompanyName3 | exmple3 |description3 | 2016 |
| 4 |CompanyName4 | exmple4 |description4 | 2016 |
+-----+-------------+---------+---------=------+-----------+
Now whenever a user type any input in search bar an ajax request is made to php file which checks for if that name of user exist in database or not
so for example if user type input john then a query should run which will check john in users table and company table & if there is a user name john & if there is a company named john it should fetch both the result.
how can i achieve this, i tried using UNION in my query but it said columns are different
Currently this is my query
$go = mysqli_query($connecDB, "SELECT name, img,username FROM users WHERE name LIKE '$q%' LIMIT 0,10");
Now people might be thinking what i really want!
i want a single query that will check for input in both table & fetch their details
You can use union
select id, name ,username, image, email, null, null
from users
where name LIKE concat('$q', '%')
union all
select id, company_name as name ,username, null, null, description, founded
from Company
where name LIKE concat('$q, '%')
order by name limit 10

is it safe to run a another query in side a mysql loop

I have a left join query to get posts liked by a users. if 2nd logged in user visit the 1st user profile will show the likes by 1st user and also will show a text on the post if 2nd user (logged in user) like the same post
user table
user_id | username
likes table
like_id | post_id | uid
MySQL
$SQL = "SELECT * FROM likes LEFT JOIN users ON users.user_id = likes.uid WHERE likes.uid = 'user1'"
If i run another query inside the while loop of above query it will work
$check_id = row['post_id']; //get post id from 1st loop
if(isset($_SESSION['userid'])){
$check = "SELECT * FROM likes WHERE post_id='$check_id' AND uid='LOGED-IN-USER-ID'"
}
Then i can get the num_rows and add text. This work perfectly fine but i like to know is there a better way to do this without running so many queries inside the while loop. Is there a way to combine the queries or do the 2nd query outside of the loop.
That's "safe" from "data consistency point of view", but querying in a while after a query is called a "1+N" and is typically a performance killer, you may easily find documentation about SQL 1+N problem.
The solution is to let the SQL server do the job for you in a single query, avoiding playing ping pong with it (read: TCP packets back-and-forth, query parsing, ...).
Given:
> SELECT * FROM user;
+---------+----------+
| user_id | username |
+---------+----------+
| 1 | root |
| 2 | user2 |
| 3 | user3 |
+---------+----------+
> SELECT * FROM `like`;
+---------+---------+---------+
| like_id | post_id | user_id |
+---------+---------+---------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 4 | 4 | 1 |
| 5 | 2 | 2 |
+---------+---------+---------+
> SELECT * FROM `post`;
+---------+--------+
| post_id | text |
+---------+--------+
| 1 | post 1 |
| 2 | post 2 |
| 3 | post 3 |
| 4 | post 4 |
+---------+--------+
There's multiple way to request what you want, but one way may be:
> SELECT like_id, like.post_id, text,
(SELECT 1 FROM `like`
WHERE post_id = post.post_id AND
user_id = 2 /* logged in user */) AS I_like_it_too
FROM `like`
JOIN post USING (post_id)
WHERE user_id = 1 /* user id of seen profile */;
+---------+---------+--------+---------------+
| like_id | post_id | text | I_like_it_too |
+---------+---------+--------+---------------+
| 1 | 1 | post 1 | NULL |
| 2 | 2 | post 2 | 1 |
| 3 | 3 | post 3 | NULL |
| 4 | 4 | post 4 | NULL |
+---------+---------+--------+---------------+
The use the I_like_it_too alias to display post differently as needed.
From a performance point of view you'll need an index on like.user_id to restrict the selected rows on a little subset, the dependent subquery will only be ran for this subset, so that's OK.
Another possibility may be:
> SELECT displayed.like_id, displayed.post_id, text, my_likes.like_id is not null AS i_also_like
FROM `like` AS displayed
JOIN post USING (post_id)
LEFT JOIN `like` AS my_likes ON
displayed.post_id = my_likes.post_id AND
my_likes.user_id = 2 /* logged user */
WHERE displayed.user_id = 1 /* user id of seen profile */;
+---------+---------+--------+-------------+
| like_id | post_id | text | i_also_like |
+---------+---------+--------+-------------+
| 1 | 1 | post 1 | 0 |
| 2 | 2 | post 2 | 1 |
| 3 | 3 | post 3 | 0 |
| 4 | 4 | post 4 | 0 |
+---------+---------+--------+-------------+
Do u mean like this ?
Table SO_LIKES ( ur "Like" Table )
like_id | post_id | uid
1 | 1 | 1
2 | 2 | 1
3 | 1 | 2
Table SO_USERS ( ur "Users" Table )
user_id | username
1 | User1
2 | User2
SQL
SELECT * FROM SO_LIKES as t1 LEFT JOIN SO_USERS as t2 ON t1.uid = t2.user_id INNER JOIN SO_LIKES as t3 ON t1.post_id = t3.post_id WHERE t2.user_id = 1 AND t3.uid = 2
SO Simply call the Same Table in ur query again and use the ID of user 2 there
WHERE t2.user_id = 1 AND t3.uid = 2
Output Looks then like this
like_id | post_id | uid | user_id | username | like_id | post_id | uid
1 | 1 | 1 | 1 | User1 | 3 | 1 | 2
SO u get the POST_id 1 That both Users has Liked

How to select multiple data from other table from each id separated by comma in codeigniter

I have the tables like this
tbl_post
+-----------+--------------+
| post_id | post_content |
+-----------+--------------+
| 1 | contentone |
+-----------+--------------+
tbl_category
+-------------+---------------+
| category_id | category_name |
+-------------+---------------+
| 1 | Politic |
| 2 | Social |
| 3 | Economy |
+-------------+---------------+
tbl_category_post
+------------------+-------------+---------+
| category_post_id | category_id | post_id |
+------------------+-------------+---------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
+------------------+-------------+---------+
then I want the output like this
+--------------+--------------------------+
| post_content | category |
+--------------+--------------------------+
| 1 | Politic, Social, Economy |
+--------------+--------------------------+
and then how to show the data like this using codeigniter, I really confused at all, anyone please help me!
Edit: With Codeigniter (not tested):
$this->db->select('post_id, GROUP_CONCAT(tc.category_name) AS category_name')
->from('tbl_category_post tcp')
join->('tbl_category tc', 'tc.category_id=tcp.category_id', 'left')
->group_by('tcp.post_id');
I suppose You need PHP loop method to loop this.
Use mysql GROUP_CONCAT function:
SELECT post_id, GROUP_CONCAT(tc.category_name) AS category_name
FROM tbl_category_post tcp
LEFT JOIN tbl_category tc ON tc.category_id=tcp.category_id
GROUP BY tcp.post_id

Categories