using subselect in mysqli - mysql

I have a query which works currently, but we added more the possibility of one customer doing more than one test drive. this additional test Drive is on a different table. The customer ID is an auto increment number on the testdriveform table. So I need to check for addition entries, based on the customer id from table 1 in table 2 and list them along withe the rest.
SELECT * FROM testdriveform Where SalesAgent not like '%Test%' and SalesAgent like '%$Sales%' and Date between '$sDate' and '$eDate' and Stock != '' order by Date, SalesAgent;
I need to add a subselect I think. Something that adds
SELECT * FROM testdrives WHERE custID = testdriveform.id
phpmyadmin is down on bluehost..again. Anyone?

NO, you don't need a subselect; rather need a JOIN between the tables like
SELECT td.*, tdf.*
FROM testdriveform tdf
JOIN testdrives td ON td.custID = tdf.id
Where tdf.SalesAgent not like '%Test%'
and tdf.SalesAgent like '%$Sales%'
and tdf.`Date` between '$sDate' and '$eDate'
and tdf.Stock != ''
order by tdf.`Date`, tdf.SalesAgent;

Related

SQL: Replacing NULL with 0 in monthly count table

I have a table named GAINLP
The table contains fields
'Record#" (INT),
'SightingDate' (DATE),
'SpeciesName' (VARCHAR)
Need SQL to output an array that contains an integer that corresponds to the sum of SightingDate for each month.
Example: 0,0,0,0,1,5,10,12,5,3,0,0
Instead, the following code causes null value sums to be skipped and I'm left with 1,5,10,12,5,3
`select count(SightingDate) from GAINLP where SpeciesName LIKE '%Actias luna' GROUP BY MONTH(SightingDate)`
I understand that this can be done by joining with a calendar table, but I've not found examples of such code that also employs the WHERE operator.
You could use conditional aggregation here:
SELECT
MONTH(SightingDate) AS month,
COUNT(CASE WHEN SpeciesName LIKE '%Actias luna' THEN 1 END) cnt
FROM GAINLP
GROUP BY
MONTH(SightingDate);
But, this might not be as efficient as a calendar table based join approach. Here is how you might do that:
SELECT
t1.month,
COUNT(t2.SightingDate) cnt
FROM (SELECT DISTINCT MONTH(SightingDate) AS month FROM GAINLP) t1
LEFT JOIN GAINLP t2
ON t1.month = MONTH(t2.SightingDate)
WHERE
t2.SpeciesName LIKE '%Actias luna'
GROUP BY
t1.month;
Note: It might be possible that your data could span more than a given year, in which case you would probably want to report both the year and month.
You seem to be looking for conditional aggregation. The principle is to move the filtering logic to a CASE construct within the aggregate function.
SELECT
SUM(
CASE
WHEN SpeciesName LIKE '%Actias luna'
THEN 1
ELSE 0
END
)
GROM gainlp
GROUP BY MONTH(SightingDate)

SQL: have duplicates for each ID, I would like to keep the ID with site that is not blank

ID Site
a www.google.com
a
b www.qq.com
b
c www.hodes.com
.
.
.
I have a table like the one above, I'd like to extract the the site value is not blank, such as:
ID Site
a www.google.com
b www.qq.com
c www.hodes.com
You just have to check if the content of the column site is null or not. In order to select the rows with content:
SELECT * FROM TABLE_NAME WHERE SITE IS NOT NULL
Read more here.
select * from table where Site <> '' or Site is not null
will work if the blank ones are ALWAYS duplicates.
otherwise
select max(id), max(site) from table group by id
Should be okay
select
ID,
max(if(trim(site) = '', null, site)) as site
from tbl
group by ID
;
You could substitute GROUP_CONCAT for max if more than one site per ID.
I'm gonna go on a limb and assume that you want to remove the empty rows from your database. If that's not the case, just move the where clause to a Select statement.
Delete from TableName where ISNULL(Site, '')=''
If you must return one and only one record per id, then your code must
cope with potential multiple records per id -- and you need the max() and group by .
I would suggest:
Select id, max(site)
from table_name
where nvl(site,0) <> 0
group by id
Else if you know that you'd never encounter multiple records with the same id:
Select id, site
from table_name
where nvl(site,0) <> 0

sql select to extract and link the record above

I need some assistance with my extract. Below is a view of my data and how it is extract from a MS SQL database.
My challenge is that the database does not differentiate from the different "email address" . How do I link email address record to the record above.
Secid|Name|Question|Answer|
2|load1|Name of Principle|Joe Make|
2|load1|Contact Number|12234423|
2|load1|Email address|joemake#mymail.com|
2|load1|Name of Principle|Amy Soup|
2|load1|Contact Number of Principle|23134|
2|load1|Email address|amysoup#mymail.com|
2|load1|Name of Teacher|james blue|
2|load1|Contact Number|8787878|
2|load1|Email Address|jamesblue#mymail.com|
2|load1|Name of Secretary|CHARLES black|
2|load1|Contact Number|989897|
2|load1|Email Address|chblack#mymail.com|
If you don't have any column to order by (e.g. a monotonically increasing identity column, or a timestamp), I'm afraid you're honestly out of luck. There is no way to guarantee any sort of ordering of the rows for any query.
What you can do, however, is export the data into an Excel sheet and then look at it manually and put the rows in the right order, assuming you can figure it out. Unfortunately this is really going to be the only way.
If you had a column you could order by, you can use a join to group the rows, assuming you had a way of identifying the start of each set - in your case a Question like 'Name of %' should probably work. Assuming an identity column called Id, something like:
select t.*, tGroupStart.Id as GroupId
from myTable t
join myTable tGroupStart on tGroupStart.Id <= t.Id
and tGroupStart.Question like 'Name of %'
where not exists (
select 1
from myTable t2
where t2.Id <= t.Id
and t2.Question like 'Name of %'
and t2.Id > tGroupStart.Id
)

mysql search query returns the same record x times

I have the following mysql query
SELECT *, DATE(file_created) as created, s.disk_id, s.url,
(SELECT COUNT(*) FROM Comments WHERE cmt_type=1 AND file_id=cmt_id) as comments FROM (files, servers s)
WHERE usr_id=1 AND (file_name LIKE CONCAT('%','sample','%') OR file_descr LIKE CONCAT('%','sample','%'))
ORDER BY file_created DESC
When I run this query I get 40 records back if there is atleast one record matching the query and all the 40 results will be the same record with the same ID!
I cant see any obvious problems with the query so not sure what is causing this problem.
Here is your query, formatted so it is better understood:
SELECT *, DATE(file_created) as created, s.disk_id, s.url,
(SELECT COUNT(*) FROM Comments WHERE cmt_type=1 AND file_id=cmt_id) as comments
FROM files, servers s
WHERE usr_id = 1 AND
(file_name LIKE CONCAT('%','sample','%') OR file_descr LIKE CONCAT('%','sample','%'))
ORDER BY file_created DESC
You have no join condition between files and server. No surprise that you ware getting duplicates. The comma in the from clause means cross join or "create a cartesian product". Simply do not use commas in the from clause. A simple rule that will save future frustration.
So, if the file has a server id, then you might want:
SELECT *, DATE(file_created) as created, s.disk_id, s.url,
(SELECT COUNT(*) FROM Comments WHERE cmt_type=1 AND file_id=cmt_id) as comments
FROM files JOIN
servers s
ON files.serverid = s.serverid
WHERE usr_id = 1 AND
(file_name LIKE CONCAT('%','sample','%') OR file_descr LIKE CONCAT('%','sample','%'))
ORDER BY file_created DESC
You are joining two tables (files and servers) but I can't see anything to restrict the servers, so it's going to repeat each matching line of files with each matching line of servers (all of them, I suppose).
I think,
First, you should add joining criteria for tables like files.server_id = servers.id at the where statement.
Second, you should change file_id=cmt_id statement to comments.file_id = file_id for correct counts.
SELECT *, DATE(file_created) as created, s.disk_id, s.url, (SELECT COUNT(*) FROM Comments WHERE cmt_type=1 AND Comments.file_id = files.file_id) as comments
FROM (files, servers s)
WHERE files.file_server_id = s.server_id AND usr_id=1 AND (file_name LIKE CONCAT('%','sample','%') OR file_descr LIKE CONCAT('%','sample','%'))
ORDER BY file_created DESC
I hope, it works.

How to find the next record after a specified one in SQL?

I'd like to use a single SQL query (in MySQL) to find the record which comes after one that I specify.
I.e., if the table has:
id, fruit
-- -----
1 apples
2 pears
3 oranges
I'd like to be able to do a query like:
SELECT * FROM table where previous_record has id=1 order by id;
(clearly that's not real SQL syntax, I'm just using pseudo-SQL to illustrate what I'm trying to achieve)
which would return:
2, pears
My current solution is just to fetch all the records, and look through them in PHP, but that's slower than I'd like. Is there a quicker way to do it?
I'd be happy with something that returned two rows -- i.e. the one with the specified value and the following row.
EDIT: Sorry, my question was badly worded. Unfortunately, my definition of "next" is not based on ID, but on alphabetical order of fruit name. Hence, my example above is wrong, and should return oranges, as it comes alphabetically next after apples. Is there a way to do the comparison on strings instead of ids?
After the question's edit and the simplification below, we can change it to
SELECT id FROM table WHERE fruit > 'apples' ORDER BY fruit LIMIT 1
SELECT * FROM table WHERE id > 1 ORDER BY id LIMIT 1
Even simpler
UPDATE:
SELECT * FROM table WHERE fruit > 'apples' ORDER BY fruit LIMIT 1
So simple, and no gymnastics required
Select * from Table
where id =
(Select Max(id) from Table
where id < #Id)
or, based on the string #fruitName = 'apples', or 'oranges' etc...
Select * from Table
where id =
(Select Max(id) from Table
where id < (Select id from Table
Where fruit = #fruitName))
I'm not familiar with the MySQL syntax, but with SQL Server you can do something with "top", for example:
SELECT TOP 1 * FROM table WHERE id > 1 ORDER BY id;
This assumes that the id field is unique. If it is not unique (say, a foreign key), you can do something similar and then join back against the same table.
Since I don't use MySQL, I am not sure of the syntax, but would imagine it to be similar.
Unless you specify a sort order, I don't believe the concepts of "previous" or "next" are available to you in SQL. You aren't guaranteed a particular order by the RDBMS by default. If you can sort by some column into ascending or descending order that's another matter.
This should work. The string 'apples' will need to be a parameter.
Fill in that parameter with a string, and this query will return the entire record for the first fruit after that item, in alphabetical order.
Unlike the LIMIT 1 approach, this should be platform-independent.
--STEP THREE: Get the full record w/the ID we found in step 2
select *
from
fruits fr
,(
--STEP TWO: Get the ID # of the name we found in step 1
select
min(vendor_id) min_id
from
fruits fr1
,(
--STEP ONE: Get the next name after "apples"
select min(name) next_name
from fruits frx
where frx.name > 'apples'
) minval
where fr1.name = minval.next_name
) x
where fr.vendor_id = x.min_id;
The equivalent to the LIMIT 1 approach in Oracle (just for reference) would be this:
select *
from
(
select *
from fruits frx
where frx.name > 'apples'
order by name
)
where rownum = 1
I don't know MySQL SQL but I still try
select n.id
from fruit n
, fruit p
where n.id = p.id + 1;
edit:
select n.id, n.fruitname
from fruits n
, fruits p
where n.id = p.id + 1;
edit two:
Jason Lepack has said that that doesn't work when there are gaps and that is true and I should read the question better.
I should have used analytics to sort the results on fruitname
select id
, fruitname
, lead(id) over (order by fruitname) id_next
, lead(fruitname) over (order by fruitname) fruitname_next
from fruits;
If you are using MS SQL Server 2008 (not sure if available for previous versions)...
In the event that you are trying to find the next record and you do not have a unique ID to reference in an applicable manner, try using ROW_NUMBER(). See this link
Depending on how savvy your T-SQL skill is, you can create row numbers based on your sorting order. Then you can find more than just the previous and next record. Utilize it in views or sub-queries to find another record relative to the current record's row number.
SELECT cur.id as id, nxt.id as nextId, prev.id as prevId FROM video as cur
LEFT JOIN video as nxt ON nxt.id > cur.id
LEFT JOIN video as prev ON prev.id < cur.id
WHERE cur.id = 12
ORDER BY prev.id DESC, nxt.id ASC
LIMIT 1
If you want the item with previous and next item this query lets you do just that.
This also allows You to have gaps in the data!
How about this:
Select * from table where id = 1 + 1