Selecting columns using variables - mysql

Probably not the best description for a title but I really couldn't think of anything.
What I want to happen is that I can create a query that selects the type from listings using the userID as a relationship and then selecting the town.
TABLE listings
saleID userID type description
1 23 clothing nice clothing
2 45 clothing More nice Clothing
TABLE users
userID country county town
23 uk county townname1
24 uk county townname2
The variables are set in the url as a get eg) ?type=clothing&town=townname2
if (!isset($type)){
$query = "SELECT * FROM listings";
}
if (isset($type)) {
$query = "SELECT * FROM listings WHERE type = '{$type}'";
}
This is the bit i'm stuck on I want to get all listings with the variable $type 'clothing' and then select from users with the town of the variable $town
if (isset($town)) {
$query = "SELECT users.town listings.userID listings.type FROM listings
WHERE type = '{$type}'
INNER JOIN users
ON users.town = '{$town}'";
}
Hope I've explained this well enough to understand.
Please help me with this last query

SELECT u.town l.userID, l.type
FROM listings l
INNER JOIN users u on u.userID = l.userID
WHERE l.type = '{$type}'
AND u.town = '{$town}'

SELECT b.town, a.userID, a.type
FROM listings a
INNER JOIN users b
ON a.userID = b.userID
WHERE a.type = '{$type}' AND
b.town = '{$town}'
To further gain more knowledge about joins, visit the link below:
Visual Representation of SQL Joins
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?

Related

Beginner SQL: JOIN clause skewing results of query

thank you all for taking the time to read and help if you can! I have a query below that is getting large and messy, I was hoping someone could point me in the right direction as I am still a beginner.
SELECT
DATE(s.created_time_stamp) AS Date,
s.security_profile_id AS Name,
COUNT(*) AS logins,
CASE
WHEN COUNT(s.security_profile_id) <= 1
THEN '1'
WHEN COUNT(s.security_profile_id) BETWEEN 2 AND 3
THEN '2-3'
ELSE '4+'
END AS sessions_summary
FROM session AS s
INNER JOIN member AS m
ON s.security_profile_id = m.security_profile_id
JOIN member_entitlement AS me ON m.id = me.member_id
JOIN member_package AS mp ON me.id = mp.member_entitlement_id
**JOIN member_channels AS mc ON mc.member_id = m.id**
where member_status = 'ACTIVE'
and metrix_exempt = 0
and m.created_time_stamp >= STR_TO_DATE('03/08/2022', '%m/%d/%Y')
and display_name not like 'john%doe%'
and email not like '%#aeturnum.com'
and email not like '%#trendertag.com'
and email not like '%#sargentlabs.com'
and member_email_status = 'ACTIVE'
and mp.package_id = 'ca972458-bc43-4822-a311-2d18bad2be96'
and display_name IS NOT NULL
and s.security_profile_id IS NOT NULL
**and mc.id IS NOT NULL**
GROUP BY
DATE(created_time_stamp),
Name
ORDER BY
DATE(created_time_stamp),
Name
The two parts of the query with asterisks are the two most recently added clauses and they skew the data. Without these, the query runs fine. I am trying get a session summary which works fine, but I only want the sessions of people who have a 'channel' created. Maybe mc.id IS NOT NULL is not the way to do this. I will share my query that shows me how many people have created channels. Essentially, I am trying to combine these two queries in the cleanest way possible. Any advice is greatly appreciated!
-- Users that have Topic Channels and Finished Set Up FOR TRIAL DASH**
select count(distinct(m.id)) AS created_topic_channel
from member m right join member_channels mc on mc.member_id = m.id
left join channels c on c.id = mc.channels_id
JOIN member_entitlement AS me ON m.id = me.member_id
JOIN member_package AS mp ON me.id = mp.member_entitlement_id
where title not like '# Mentions'
and member_status = 'ACTIVE'
and metrix_exempt = 0
and m.created_time_stamp >= STR_TO_DATE('03/08/2022', '%m/%d/%Y')
and display_name not like 'john%doe%'
and email not like '%#aeturnum.com'
and email not like '%#trendertag.com'
and email not like '%#sargentlabs.com'
and member_email_status = 'ACTIVE'
and display_name IS NOT NULL
and mp.package_id = 'ca972458-bc43-4822-a311-2d18bad2be96';
The metric I am trying to retrieve from the DB is how many users have created a channel and logged in at least twice. Thank you again and have a wonderful day!!
If id is the primary key of member_channels then it does not make sense to check if it is null.
If all you want is to check whether a member has a 'channel' created, then instead of the additional join to member_channels, which may cause the query to return more rows than expected, you could use EXISTS in the WHERE clause:
where member_status = 'ACTIVE'
and .......................
and EXISTS (SELECT 1 FROM member_channels AS mc WHERE mc.member_id = m.id)
I would guess your tables aren't at the same level of granularity. A member may have many sessions, and 0-many channels.
eg if member 123 has five sessions and creates three channels => 15 rows of data in this join.
To adjust for this, it's best practice to join on the same level of granularity. You could roll up sessions to the member level, channels to the member level, and then join both against members.

How to export user data from two different tables using the backoffice sql manager of Prestashop?

I'm not good with sql so i need help exporting my customer's first names, email address, their country and if possible last times they had access to the store.
I managed to get email and first name by using this query :
SELECT firstname, lastname, email, active FROM psdb_customer
From what i understood, since the other data is stored in a different db table, i should use a join to get data from both tables but i haven't been able to figure out how
Any help is welcome
In the past, I helped someone with something similar in the PrestaShop forum. This query should work, just remember that to get a country of a customer they should have at least one address registered and of course I'm using the default db prefix:
SELECT a.`firstname`,
a.`lastname`,
a.`email`,
(SELECT c.`date_add`
FROM `ps_guest` g
LEFT JOIN `ps_connections` c ON c.`id_guest` = g.`id_guest`
WHERE g.`id_customer` = a.`id_customer`
ORDER BY c.`date_add` DESC LIMIT 1) AS `last_activity`,
(SELECT cl.`name`
FROM `ps_address` ad
LEFT JOIN `ps_country_lang` cl ON cl.`id_country` = ad.`id_country`
WHERE ad.`id_customer` = a.`id_customer`
ORDER BY ad.`id_address` DESC LIMIT 1) AS `country_name`
FROM `ps_customer` a
Rolige's answer is what i was looking for.
Here is another query that allows filtering the results by country (using the id_country)
SELECT SQL_CALC_FOUND_ROWS a.`id_address`,
a.firstname as firstname,
a.lastname as lastname,
cl.id_country as country, cl.`name` as country
FROM `ps_address` a
LEFT JOIN `ps_country_lang` cl ON (cl.`id_country` = a.`id_country`
AND cl.`id_lang` = 1)
LEFT JOIN `ps_customer` c ON a.id_customer = c.id_customer
WHERE 1 AND a.id_customer != 0
AND c.id_shop IN (1)
AND a.`deleted` = 0
AND cl.`id_country` = '8'
ORDER BY a.`id_address` ASC

SQL just do the opposite of this

SELECT Name FROM Anime LEFT JOIN anime_user2 ON anime_idAnime = idAnime WHERE users_userID = $userID
I want to get the exact opposite of this but it's not working with
WHERE users_userID != $userID
I get 4 Names, but I want every Name except those 4 Names.
Do you how to do this?
You can use NOT IN operator like this:
SELECT NAME
FROM ANIME a
WHERE a.NAME NOT IN (
SELECT Name
FROM Anime LEFT JOIN anime_user2 ON anime_idAnime = idAnime
WHERE users_userID = $userID
)
BEWARE: Depending on what is your table histogram, this query might be too slow to use it on a web page or application.

MYSQL query not working as wanted

I want to be able to get the pieces evidence within a trybe. But I have to go through the ambition table which is the relation from trybe to evidence.
So basically get count(e.id) from
The query i have at the moment is as follows:
$evidence = array(1,2,10,20,40,60,80,100,200,300,400,500,1000,1500,2000);
$evidence = implode(", ", $evidence);
# no of evidence in trybe = the x trybe now has over x evidence
$query = sprintf("SELECT t.id, t.name, COUNT(e.id) as number, 'trybe_evidence' AS type
FROM x_trybes t
INNER JOIN x_ambition_owner ao ON (t.id = ao.trybe_id)
LEFT JOIN x_evidence e ON (ao.id = e.ambition_id)
GROUP BY t.id, t.name
HAVING COUNT(e.id) in (%s)",$evidence);
How can I get all the pieces of evidence from all the ambitions within the trybe table?
The structure of the tables are as follows:
x_trybes
id name
x_ambition_owner
id ambition_id trybe_id
x_ambition - ambition info
id name etc.
x_evidence
id ambition_id name
Please note there can be many trybes, many ambitions and many pieces of evidence.
Thanks

MySQL Left Join Not Working

I am trying to just select data from table agency where that agency has entry in the commission table with a certain carrier. My SQL query is returning all entries and 3 times. What am I doing wrong.
$allquery = mysql_query("SELECT agency.ID, agency.agencyname, agency.contdate, agency.physcity FROM agency LEFT JOIN commission ON commission.repnum = agency.repid WHERE agency.repid = '$repid' AND commission.repnum = '$repid' AND commission.carrier = 'Carrier' ")or die(mysql_error())
You are not joining two tables unless you actually specify a join criteria involving columns from each table.
SELECT agency.ID, agency.agencyname, agency.contdate, agency.physcity
FROM agency LEFT JOIN commission ON commision.repid = agency.repid AND commission.carrier = 'Carrier'
Q: Why don't you use an inner join if you want to refer to elements in "commission"?
Q: Why are you doing a join at all??? I don't see how "commission" is linked to "agency". Does "commission" have a "repid" field, too?
Anyway, based on what you've shown, I'd recommend this:
SELECT ID, agencyname, contdate, physcity
FROM agency
where repid = '$repid'