MySQL query to search for all records against field with comma separated values - mysql

I have 2 sql tables
Table name: agents contains a records with a coloumn AgentID
Table named: vacancies is the one with the data ans is being dislayed.
Table named vacancies has vacancies.Agents which contains values simmilar to this
VacanyID Company position CTC Candidates Agents
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FBVAC001 | HDFC | Branch Manager | 4.5 | FBCAN001,FBCAN002| Agent3,Agent4
FBVAC003 | TBNH | Branch Manager | 4.5 | FBCAN004,FBCAN005| Agent2,Agent4
FBVAC005 | MMNT | Branch Manager | 4.5 | FBCAN008,FBCAN006| Agent3
FBVAC008 | LCFC | Branch Manager | 4.5 | FBCAN009,FBCAN023| Agent3,Agent4
FBVAC008 | KOTC | Branch Manager | 4.5 | FBCAN009,FBCAN023| Agent5,Agent4
I want to run a query that will return only those records that contain the value that corresponds to agents.AgentID from table name agents. This is the query so far but all it returs are those records that do not have more than one value in vacancies.Agents
for example if the value being searched for is Agent3 it should return rows1,3 and 4 instead it only returns row 3.
SELECT
vacancies.VacancyID,
vacancies.Company,
vacancies.`Position`,
vacancies.CTC,
vacancies.Candidates,
vacancies.Agents
FROM vacancies
, agents
WHERE (FIND_IN_SET(vacancies.Agents,agents.AgentID) <> 0)
How can this be resolved?

I believe you have your parameters backwards in FIND_IN_SET. The set should come second
FIND_IN_SET(agents.AgentID, vacancies.Agents)
More Info: http://www.bitbybit.dk/carsten/blog/?p=162
Also, if you are wanting to see only a specific agent, you need to filter for that as well, otherwise you're getting every possible combination of agent and matching vacancies (hence the duplicate rows):
AND Agents.AgentID = 'Agent3'
Demo: http://www.sqlfiddle.com/#!2/b4dcb/3

SELECT
vacancies.VacancyID,
vacancies.Company,
vacancies.`Position`,
vacancies.CTC,
vacancies.Candidates,
vacancies.Agents
FROM vacancies,
agents
WHERE (select
agents.agentid,
vacancies.agentid
from agents
left join vacancies
on vacancies.agentid = agents.agentid)
and agents.agentid = 'Agent3'

Related

Adding entries from multiple MySQL tables using one single SQL join statement, but only if there are entries available in the second table

Using one single SQL query with a join:
How can I add entries from a second table only if there is a corresponding entry available?
project source
description | source source_id | value
---------------------------- --------------------------------
Project 1 | 1 1 | Additional Info 1
Project 2 | null
When I type
select project.description, source.value
from project, source
where project.source = source.source_id
and project.description = "Project 1";
As desired I receive
Project 1 | Additional Info 1
However when I replace Project 1 with Project 2 in the last line, I won't get a result, because project.source is null.
Is it possible to use a single SQL query which outputs something like this?
Project 2 | null
I´m looking for a query which covers both cases.
Any ideas?
You can use a LEFT JOIN on the project table to make sure that all projects appear in the result set even if they have no matching value in the source table. Projects from the project table which do not match will have NULL for their value.
SELECT project.description AS description, source.value AS value
FROM project LEFT JOIN source
ON project.source = source.source_id
Output:
+--------------+--------------------+
| description | value |
---------------+--------------------+
| Project 1 | Additional Info 1 |
| Project 2 | null |
+--------------+--------------------+
Try to use left join....
SELECT project.description, source.value FROM project LEFT JOIN source ON project.source = source.source_id;

export phpList subscribers via sql in mysql database

For some reason, I am unable to export a table of subscribers from my phpList (ver. 3.0.6) admin pages. I've searched on the web, and several others have had this problem but no workarounds have been posted. As a workaround, I would like to query the mySQL database directly to retrieve a similar table of subscribers. But I need help with the SQL command. Note that I don't want to export or backup the mySQL database, I want to query it in the same way that the "export subscribers" button is supposed to do in the phpList admin pages.
In brief, I have two tables to query. The first table, user contains an ID and email for every subscriber. For example:
id | email
1 | e1#gmail.com
2 | e2#gmail.com
The second table, user_attribute contains a userid, attributeid, and value. Note in the example below that userid 1 has values for all three possible attributes, while userid's 2 and 3 are either missing one or more of the three attributeid's, or have blank values for some.
userid | attributeid | value
1 | 1 | 1
1 | 2 | 4
1 | 3 | 6
2 | 1 | 3
2 | 3 |
3 | 1 | 4
I would like to execute a SQL statement that would produce a row of output for each id/email that would look like this (using id 3 as an example):
id | email | attribute1 | attribute2 | attribute3
3 | e3#gmail.com | 4 | "" | "" |
Can someone suggest SQL query language that could accomplish this task?
A related query I would like to run is to find all id/email that do not have a value for attribute3. In the example above, this would be id's 2 and 3. Note that id 3 does not even have a blank value for attributeid3, it is simply missing.
Any help would be appreciated.
John
I know this is a very old post, but I just had to do the same thing. Here's the query I used. Note that you'll need to modify the query based on the custom attributes you have setup. You can see I had name, city and state as shown in the AS clauses below. You'll need to map those to the attribute id. Also, the state has a table of state names that I linked to. I excluded blacklisted (unsubscribed), more than 2 bounces and unconfirmed users.
SELECT
users.email,
(SELECT value
FROM `phplist_user_user_attribute` attrs
WHERE
attrs.userid = users.id and
attributeid=1
) AS name,
(SELECT value
FROM `phplist_user_user_attribute` attrs
WHERE
attrs.userid = users.id and
attributeid=3
) AS city,
(SELECT st.name
FROM `phplist_user_user_attribute` attrs
LEFT JOIN `phplist_listattr_state` st
ON attrs.value = st.id
WHERE
attrs.userid = users.id and
attributeid=4
) AS state
FROM
`phplist_user_user` users
WHERE
users.blacklisted=0 and
users.bouncecount<3 and
users.confirmed=1
;
I hope someone finds this helpful.

MySQL pull data from same table, SUM multiple columns with conditions

I have created a users table that holds names and phone numbers (users).
id| name | phone
1 | Frank | 0345221234
2 | Sara | 0342555939
I got another table that holds a log with user's calls to different numbers (call_logs):
number | destination | price
0345221234 | destination | x /// This is Frank
0345221234 | destination | y /// This is also Frank
0342555939 | destination | z /// This is Sara
And then I have a table that holds numbers that Frank and Sara are allowed to call (allowed_numbers):
number
033485733
045727728
082358288
I would like to loop through my users table and based on their number to check the calls log table and select the SUM of price column for log records where destination does not match the allowed numbers table so that I know the cost for calls not in the allowed list.
Then I want to select SUM of price column for log records where destination DO match
the allowed numbers table so that I know how much did the allowed calls cost.
Is there any way I can do this in a single query with sub-queries and all needed in order to achieve this result set:
users number | SUM(price) of allowed calls | SUM(price) of calls not allowed
Thank you!
SELECT call_logs.number
,SUM(IF(allowed_numbers.number IS NOT NULL,call_logs.price,0)) AS AllowedPrice
,SUM(IF(allowed_numbers.number IS NULL,call_logs.price,0)) AS NotAllowedPrice
FROM call_logs
LEFT JOIN allowed_numbers
ON call_logs.destination = allowed_numbers.number
GROUP BY call_logs.number;

Microsoft Access 2003 Query - Count records and sum it

I'm creating a query with Microsoft Access 2003 and had encounter an issue. I'm new!
I've got 2 tables. First table, i have a list of records that include the name, property name and the country state. Second table, i have a list of property names, the number of units in the property and the property's country state.
I will like to count the number of records in the first table by its state, meanwhile summing up the number of units the property has in the state.
What I encountered is, when I sum the number of units, the units repeats!
Taking for example;
Table1:
Name | State | Property Name
Mr 1 | State A | Building AAA
Mr 2 | State A | Building AAA
Mr 3 | State A | Building BBB
Mr 4 | State B | Building XXX
Mr 5 | State B | Building XXX
Table2:
Property Name | State | Number of Units
Building AAA | State A | 100
Building BBB | State A | 50
Building XXX | State B | 20
My Result:
State | Number of Units | No of Records
State A | 250 | 3
State B | 40 | 2
The result i want:
State | Number of Units | No of Records
State A | 150 | 3
State B | 20 | 2
EXPANDED
Assuming you are using the Access query builder, you will need to construct three Select queries:
1) Table1 will be the source table for the first query. Use the State field twice in the query, first as a Group By field and second as a Count field. (Any of the fields could have been used for the count, since you are only interested in the number of records.) Save the query for use in the third query.
2) Table2 will be the source table for the second query. Use the State field as a Group By field and the Units field as a Sum field. Save this query, too.
3) The third query will bring the information together. For the source, use the first and second queries, with a join between them on the State field. Select the State field (from either query) as a Group By Field, the CountOfState field from the first query as a Sum field, and the SumofUnits field from the second query as a Sum field.
While the actual amount of work done by Access in producing the final result will not change, the three queries can be consolidated into a single query by editing the underlying SQL.
The new query was produced by inserting the Table1 and Table2 queries into the third, final result query, one on either side of the INNER JOIN statement. The T1 and T1 in the new query are aliases for the embedded queries that eliminate ambiguity in referencing the fields of those queries.
The new query cannot be created using the Query Builder (although the original three queries provide the raw material for it). Instead, the SQL must be written/pasted in/edited in the SQL View of the Query Builder.
SELECT T1.State AS State,
Sum(T1.CountOfState) AS Records,
Sum(T2.SumOfUnits) AS Units
FROM
(SELECT Table1.State,
Count(Table1.State) AS CountOfState
FROM Table1
GROUP BY Table1.State) T1
INNER JOIN
(SELECT Table2.State,
Sum(Table2.Units) AS SumOfUnits
FROM Table2
GROUP BY Table2.State) T2
ON T1.State = T2.State
GROUP BY T1.State;

Summary of MySQL detail records matching by IP address ranges - mySQL Jedi Knight required

So, I have to draw upon all the powers of the greatest mySQL minds that SO has to offer. I have to summarize detail records based on the IP address in each record. Here's the scenario:
In short, we have consortiums that want to know: "Which schools within my consortium watched which videos how many times"? In SQL terms, it amounts to COUNTing the detail records, grouped by which IP range it might fall into.
We have several university Consortiums - each with a handful of different schools that are members.
Each school within a consortium uses various IP ranges to access the videos that we serve to these schools.
The IP Ranges are specified with wild cards, so each school specifies something like '100.200.35.x, 100.201.x.x, 100.202.39.50, etc.', with the average number of ranges per school being 10 or 15.
The raw text log files to summarize are already in a database (one row for each log entry), and has the actual IP address that accessed the video file.
There are 100's of millions of detail records, so I fully expect this to be a long slow process that runs for a considerable period.
PHP scripts exist that can "explode" the wildcards into the individual IPs that are represented, but I fear this will be the final answer and could take weeks to run.
(For simplicity sake, I'm only going to refer to the video filename that was accessed and COUNT the log entries for it, but in fact all the details such as start/stop/duration,etc. are there and will ultimately be part of this solution.)
With Consortium records something like this: (All table designs except log details open to suggestion):
| id|consortium |
| 10|Ivy League |
| 20|California |
And School/IP records something like this:
| id|school |consortium_id|
| 101|Harvard |10 |
| 102|Yale |10 |
| 103|UCLA |20 |
| 104|Berkeley |20 |
| id|school_id|ip_range |
| 1| 101 |100.200.x.x |
| 2| 101 |100.201.65.x |
| 3| 101 |100.202.39.50 |
| 4| 101 |100.202.39.51 |
| 5| 101 |100.200.x.x |
| 6| 101 |100.201.65.x |
| 7| 101 |100.202.39.50 |
And detail records something like this:
|session |ip_address |filename |
|560554790925|100.202.390.500|history101.mp4 |
|406417611526|43.22.90.5 |newsreel.mp4 |
|650423700223|100.202.39.50 |history101.mp4 |
|650423700223|100.202.50.12 |science101.mp4 |
|513057324209|100.202.39.56 |history101.mp4 |
I like to think I'm pretty handy with mySQL, but this one is stretching it, and am hoping that there's a spectacular function or set of steps that someone might offer.
With your existing data structure, you could do string matching as follows (but it's not very efficient):
SELECT schools.school, detail.filename, COUNT(*)
FROM schools
JOIN ipranges ON schools.id = ipranges.school_id
JOIN detail ON detail.ip_address LIKE REPLACE(ipranges.ip_range, 'x', '%')
WHERE schools.consortium_id = ?
GROUP BY schools.school, detail.filename
A better way would be to store your IP ranges as network address and prefix length:
ALTER TABLE ipranges
ADD COLUMN network INT UNSIGNED,
ADD COLUMN prefix TINYINT;
UPDATE ipranges SET
network = INET_ATON(REPLACE(ip_range, 'x', 0)),
prefix = 32 - 8*(CHAR_LENGTH(ip_range) - CHAR_LENGTH(REPLACE(ip_range,'x',''));
ALTER TABLE ipranges
DROP COLUMN ip_range;
ALTER TABLE detail
ADD COLUMN ip_address_new INT UNSIGNED;
UPDATE detail SET
ip_address_new = INET_ATON(ip_address);
ALTER TABLE detail
DROP COLUMN ip_address,
CHANGE ip_address_new ip_address INT UNSIGNED;
Then it would merely be a case of performing some bit comparisons:
SELECT schools.school, detail.filename, COUNT(*)
FROM schools
JOIN ipranges ON schools.id = ipranges.school_id
JOIN detail ON detail.ip_address & ~((1 << 32 - ipranges.prefix) - 1)
= ipranges.network
WHERE schools.consortium_id = ?
GROUP BY schools.school, detail.filename
SELECT D.filename, S.school, COUNT(D.*)
FROM detail_records AS D
INNER JOIN ip_map AS I ON D.ip_address LIKE CONCAT(SUBSTRING(I.ip_range, 1, LOCATE('x', I.ip_range)-1), '%')
INNER JOIN school AS S ON S.id = I.school_id
INNER JOIN consortium AS C ON C.id = S.consortium_id
WHERE S.consortium_id = <consortium identifier>
GROUP BY D.filename, S.school