concatenate query result in a string - php

I am getting a db result as 3 rows (Please see image link below).
The sql statement used is
select tevmkt.ev_mkt_id, tevmkt.name, tevmkt.ev_id, tevoc.ev_oc_id,
tevoc.desc, tevoc.fb_result, tevoc.lp_num, tevoc.lp_den,
tev.start_time
from tevmkt, tev,tevoc
where tevmkt.name = '|Match Result|' and tev.ev_id=tevmkt.ev_id and
tevoc.ev_mkt_id=tevmkt.ev_mkt_id and tev.start_time>=Today;
I will like to use php to concatenate each of the 3 rows into string or maybe use SQL statement.
So, the first 3 rows will display as ;
632274|Match Result||Draw||Aldershot Town||Arsenal FC|
And the next 3 rows
637799|Match Result||Draw||Southend United||Oxford United|

You can use concat
Sample base on your query
select CONCAT(tevmkt.ev_mkt_id, tevmkt.name, tevmkt.ev_id, tevoc.ev_oc_id,
tevoc.desc, tevoc.fb_result, tevoc.lp_num, tevoc.lp_den,
tev.start_time)
from tevmkt, tev,tevoc
where tevmkt.name = '|Match Result|' and tev.ev_id=tevmkt.ev_id and
tevoc.ev_mkt_id=tevmkt.ev_mkt_id and tev.start_time>=Today;

For what I see your model looks something like this:
CREATE TABLE tevmkt(
ev_mkt_id INT,
ev_id INT,
name CHAR(25)
);
CREATE TABLE tev(
ev_id INT,
start_time DATETIME YEAR TO SECOND
);
CREATE TABLE tevoc(
ev_mkt_id INT,
desc CHAR(25),
fb_result CHAR(1),
lp_num SMALLINT,
lp_den SMALLINT
);
You join tevmkt with tev by ev_id in a 1-to-1 relation.
You filter the records on tevmkt using the name field and the records on tev using the start_time field.
Now, you join the tevmkt with the tevoc by ev_mkt_id in a one to many relation, for what I see 1-to-3.
Your goal is to have a 1-to-1 also. Looking at you example I see three rows for each event and I conclude that they are:
1 row for home team, where fb_result is H;
1 row for away team, where fb_result is A;
1 row for result, I'm not sure on this one so I will handle it with care;
If this is the case, you can get your result set straigth using the next joins and filters:
SELECT
tevmkt.ev_mkt_id,
tevmkt.name,
(
TRIM(tevoc_result.desc) ||
TRIM(tevoc_away.desc) ||
TRIM(tevoc_home.desc)
) AS desc
FROM tevmkt
JOIN tev ON
tev.ev_id = tevmkt.ev_id
JOIN tevoc tevoc_result ON
tevoc_result.ev_mkt_id = tevmkt.ev_mkt_id
JOIN tevoc tevoc_away ON
tevoc_away.ev_mkt_id = tevmkt.ev_mkt_id
JOIN tevoc tevoc_home ON
tevoc_home.ev_mkt_id = tevmkt.ev_mkt_id
WHERE
tevmkt.name = '|Match Result|'
AND tev.start_time >= TODAY
AND tevoc_result.fb_result NOT IN ('H', 'A')
AND tevoc_away.fb_result = 'A'
AND tevoc_home.fb_result = 'H'
;

Related

How to set WHERE conditions if the IF() function returns FALSE and END query if it returns TRUE in mysql

I want to use mysql to check if a value exists in MySQL Database. If the value exists, I want to do nothing (I don't want to fetch any data). If it does not exist, then I want to set some where conditions.
So this is what I have so far, but its not right. because I still get data fetched, if no where condition is set
SELECT *,
CASE
WHEN ( table_name.record = 'inputrecord')
THEN
//Do nothing because it is found already
ELSE
// since inputrecord does not exist, we will start looking for 'id'
( WHERE table_name.id = '123')
END
FROM table_name
NOTE: In the above example, I have written WHEN ( table_name.record = 'inputrecord') and not WHEN ( table_name.record != 'inputrecord'). This is because I want to only continue the query if the data is not in the table.
Perhaps its better to use the IF function with the EXISTS function, but I am not sure how to do it.
Any help would be great. Right now I get errors
This is not how SQL works.
SQL always returns a collection of rows. It may be empty, sometimes rows may contain NULLs. You have to work out your conditions to filter the collection.
A generic example: say, we have a table of cars with columns (model, color, year), and you would like to find something about the cars in your table:
(* Find all red cars *)
select * from cars where color = 'red'
(* Find all red cars from 1985 *)
select * from cars where color = 'red' and year = 1985
(* Find all colors which exist both in 1990 and 2000 *)
select distinct color from cars A where year=1990 and exists (select 1 from cars B where year=2000 and B.color = A.color)
Please tell exactly what you are trying to achieve
EDIT: this should do it
(* select a record cars = 'Audi' only if cars = 'BMW' is not found in the whole table. otherwise. I do not want to select Audi even if it exists *)
select * from cars where model = 'Audi' and not exists (select 1 from cars where model = 'BMW')
here, IF there are BMWs in your table you'll get 0 rows, otherwise a list of Audis
select *
from table_name
where case when table_name.record <> 'inputrecord'
then table_name.id = '123'
else 1=1
end
you can apply the given condition in your code
when input condition does not match then apply your filter condition.
when input condition match(else case )then retrieve your desired result.
Try This...
SELECT *
CASE
WHEN table_name.record = 'inputrecord' THEN 'Unspecified'
WHEN table_name.id = '123' THEN 'table by id'
END
FROM table_name;

Propel: Getting query results from 2 db tables even when second table has no corresponding entries

My Problem: Getting query results from 2 db tables with PROPEL2 even when second table has no corresponding entries. If the second has corresponding entries than it is no problem.
I have 3 tables: Entry, Contingent and Favorit.
The schema is as follow:
Entry.id [PK]
Entry.contingent_id [FK]
Entry.expert_id
Contingent.id [PK]
Contingent.name
Favorit.id [PK]
Favorit.contingent_id [FK]
Favorit.expert_id
Favorit.pos
I want to get for a specified expert_id ($id) all entries from Entry with contingent-name and if exists the favorit.pos for this expert and contingent. I get the wanted with:
$result = EntryQuery::create()
->filterByExpertId($id)
->join('Entry.Contingent')
->withColumn('Contingent.name','_contingentName')
->join('Contingent.Favorit')
->where('Favorit.expert_id = ?', $id)
->find();
This works only if there exists such a favorit.pos . In some cases this element doesn’t exists (what is wanted from the system). In these cases I want to get the result too just with favorit.pos as empty, null or 0. But Propel doesn’t return me these records.
With MySQL I have no problem to get the desired result:
SELECT entry.* ,
(SELECT favorit.position
FROM contingent, favorit
WHERE
favorit.expert_id = entry.expert_id
AND entry.contingent_id = contingent.id
AND contingent.id = favorit.contingent_id
)
FROM `entry`
JOIN contingent
ON entry.contingent_id = contingent.id
WHERE
entry.expert_id=1;
Use Join left in code:
->join('Contingent.Favorit','selection conditon','left' )
This left work when empty database when condition is false
in condition like 'id'=$id

using mysql stored-function with select query

let me explain my purpose first, i have an vehicle booking application where, visitor will add start date and end date of his journey, in the database there is list of drivers with there availability (available_from_date and available_to_date) which is kind of duration during which they are operating, there is an field for exclude_dates for some specific dates when they are not working.
the application needs to find a list of vehicles which are available during the journey dates entered by the user.
for example user enters he want to go from place A to B during 13th sept, 2014 to 17th sept, 2014
then database needs to return a list of taxi which are available during this period and must not have any exclude date within this period.
Now i have stored the exclude_dates in comma separated format in table (i could have created a separate table but then it would take much more time for a query to execute)
I was trying to create a mysql function which would be called within the actual search query and would return true if there is some there is some excluded date present within the duration and false if not.
these are the queries that i have written
SELECT id, exclude_dates
FROM `taxi_route`
WHERE status = 1
AND `to_city` = 'Surat'
AND `from_city` = 'Ahmedabad'
AND `trip_type` = 2
AND `available_from_date` <= '2014-09-13'
AND available_to_date >= '2014-09-17'
AND STR_TO_DATE((SELECT `split`(exclude_dates, ',', 1)),'%d-%m-%Y')
NOT BETWEEN STR_TO_DATE('13-09-2014','%d-%m-%Y')
AND STR_TO_DATE('17-09-2014','%d-%m-%Y')
Split is a function i have created in mysql to separate the dates present in comma format
DELIMITER $$
CREATE FUNCTION split( str VARCHAR(500), delchar VARCHAR(2), x INT )
RETURNS VARCHAR(500)
BEGIN
RETURN SUBSTR(SUBSTRING_INDEX(str, delchar, x),
LENGTH(SUBSTRING_INDEX(str, delchar, x-1))+IF(x > 1, 2, 1));
END$$
DELIMITER ;
this works fine as far as i pass 1 in split(exclude_dates, ',', 1) , but if the exclude_dates have more then one date then this will not work
can someone please suggest or guide, how this can be accomplished.
snapshot of database is here http://i.imgur.com/JaI8MSx.png
Your query is most likely going to take more time to execute than defining a separate table for exclusion dates. It's not a good practice using comma separated list inside a column for searching purposes, this is against normalization rules.
You should define your tables separately, (e.g. taxi, taxi_route, taxi_route_exclusion, route_exclusion) and later add necessary indexes to make your searches more efficient.
Example:
taxi
---------
id
country
***
***
***
taxi_route
-------------------
id
taxi_id
available_from_date
available_to_date
from_city
to_city
route_exclusion
---------------
id
taxi_id
exclusion_date
And also add a relation table between taxi_route and route_exclusion tables to represent many-to-many relationship. Later define foreign keys on taxi_route_route_exclusion table to point taxi_route and route_exclusion tables.
taxi_route_route_exclusion
--------------------------
taxi_route_id
route_eclusion_id
Define foreign keys like:
taxi_route.taxi_id -> taxi.id
taxi_route_route_exclusion.taxi_route_id -> taxi_route.id
taxi_route_route_exclusion.route_exclusion_id -> route_exclusion.id
Define indexes like:
taxi: IX1 (status, trip_type)
taxi_route: IX1(to_city, from_city, available_from_date, available_to_date)
Your final query should look like this:
SELECT tr.id, re.exclusion_date
FROM `taxi_route` tr JOIN `taxi_route_route_exclusion` trre
ON tr.id = trre.taxi_route_id
JOIN `route_exclusion` re
ON re.id = trre.route_exclusion_id
JOIN `taxi` t
ON t.id = tr.id
WHERE
t.status = 1
AND t.trip_type = 2
AND tr.to_city = 'Surat'
AND tr.from_city = 'Ahmedabad'
AND tr.available_from_date <= '2014-09-13'
AND tr.available_to_date >= '2014-09-17'

PHP MySQL - Find Row ID

I have a table called "participants" that has 3 fields:
prt_id
prt_event_id
prt_participant_id
What I have is a select query with a where condition on event_id. The query returns let's say 20 rows (20 different participants). What I would like to do is to be able to figure out the row number for a given participant (prt_id).
SELECT *
FROM participants
WHERE prt_id = someinteger
While you can't specifically find a row ID using MySQL, you could do something like the following:
$conn = new mysqli(/*dbinfo*/);
$res = $conn->query("SELECT prt_id FROM participants");
$rowids = array(); $currid = 1;
while ($row = $res->fetch_object()) { // this is using the mysqli library
$rowids[$row->prt_id] = $currid;
$currid++;
}
This would give you an array of ids associated with prt_id.
You could do something like:
<?php
$counter = 1; // Start at one for first entry
$res = mysql_query("SELECT * FROM participants WHERE prt_id = 12");
while( $array = mysql_fetch_assoc($res) )
{
// Do something with the counter, store it into array with details
$counter++;
}
?>
This should do what you want inside MySQL (ie assign a rownum in the order of prt_id), but the performance will be dependent on the number of rows in the table so it's not optimal.
SELECT * FROM (
SELECT #tmp:=#tmp+1 rownum, p.*
FROM (SELECT #tmp:=0) z, participants p
ORDER BY prt_id
) participants
WHERE prt_id = 36;
Demo here.
Edit: This "doh level" rewrite uses an simple index range instead of a table scan, so should be much faster (provided prt_id is a PRIMARY KEY)
SELECT *, COUNT(p2.prt_id) ROWNUM
FROM participants p1
JOIN participants p2
ON p1.prt_id >= p2.prt_id
WHERE p1.prt_id=36;
Demo here.
you could just add an index column in your database, set it as int, primary key and auto increment. then when retrieving the row you retrieve the index number.
RowID is a feature of Oracle: http://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns008.htm.
MySQL does not have something like that, you can basically emulate that by assign number to an array inside php as you retrieve each row, but that doesn't guarantee you the same number next time you retrieve that results. You probably have to settle for using one of the primary IDs

Update values of database with values that are already in DB

I've a database that stores data read from different sensors. The table looks like this:
[SensorID][timestampMS][value]
[Sensor1][123420][10]
[Sensor1][123424][15]
[Sensor1][123428][6554]
[Sensor1][123429][20]
What I would like to do is the following: There are some reads that are corrupted (numbers that are 6554), and I would like to Update that with the next value that is not corrupted (in the example shown below that would be 20). So, if a number is 6554, I would like to update that with the next value (in timestamp), that is not corrupted.
I was thinking on doing this in PHP, but I wonder if it's possible to do it directly with a SQL script.
Appreciate :)
You can use a correlated sub-query...
UPDATE
myTable
SET
value = (SELECT value FROM myTable AS NextValue WHERE sensorID = myTable.SensorID AND timestampMS > myTable.timestampMS ORDER BY timestampMS ASC LIMIT 1)
WHERE
value = 6554
The sub-query gets all the following results, ordered by timestampMS and takes just the first one; That being the next value for that SensorID.
Note: If no "next" value exists, it will attempt to update with a value of NULL. To get around this, you can add this to the WHERE clause...
AND EXISTS (SELECT value FROM myTable AS NextValue WHERE sensorID = myTable.SensorID AND timestampMS > myTable.timestampMS ORDER BY timestampMS ASC LIMIT 1)
EDIT
Or, to be shorter, just use IFNULL(<sub_query>, value)...
Not sure if this is valid syntax, can't test it ATM. You may need to change this to be JOINs instead of the nested subqueries, but in concept you can do something like (for SQL Server):
UPDATE t1
SET Value = ( SELECT Value
from MyTable t2
WHERE t2.SensorID =t1.SensorID
AND t2.[timestamp] =
( SELECT MIN([TimeStamp])
FROM mytable t3
where t3.sensorid = t2.sensorID
AND t3.[timestamp] > t2.[timestamp]
)
)
FROM Mytable t1
WHERE t1.value = 6554
I did a workaround based on Dems solution, and it works in Mysql:
I've created a "copy" of the sensors table like this:
drop table if exists sensors_new;
create table if not exists sensors_new like sensors;
insert into sensors_new select * from sensors;
Then I do what Dems recommended me doing, but using this new aux table in the select (to avoid the error that Mysql launches when Updating a table while doing a select in the same table).
UPDATE
sensors
SET
raw_data = (SELECT raw_data FROM sensors_new AS NextValue WHERE sensor_id = sensors.sensor_id AND timestampMS > sensors.timestampMS ORDER BY timestampMS ASC LIMIT 1)
WHERE
value = 6554
Then, just drop this auxiliar table.
I hope this helps Mysql users.

Categories