I have a question about using the propel ORM and creating a query.
I have a table "locations" with fields:
location
sublocation
postcode
street
number
Now I want to select all the locations where the location field IS NOT equal to 'null'.
How can I do this? I've tried this but I get back all the results ...
Tried query: $locations = LocationQuery::create()->where('location' != null)->find();
You can use this:
->filterByColumnName(null, Criteria::NOT_EQUAL)
There are various 'Criteria' uses in propel, listed here: propel criteria
There isn't an exact sample for this on the site, the closest is this:
->filterByTags(array('novel', 'russian'), Criteria::CONTAINS_NONE)
You can also use
->filterByColumnName(null, CRITERIA::ISNOTNULL)
I don't know propel. But the proper SQL syntax for the expression would be:
$locations = LocationQuery::create()->where('location is not null')->find();
Any comparison to NULL in SQL returns NULL, which is treated as false. With the exception of is null and is not null.
You can reference all of the Propel 2 comparison types for CRITERIA::_needed_type_ here.
EQUAL
NOT_EQUAL
ALT_NOT_EQUAL
GREATER_THAN
LESS_THAN
GREATER_EQUAL
LESS_EQUAL
LIKE
NOT_LIKE
CONTAINS_ALL
CONTAINS_SOME
CONTAINS_NONE
ILIKE
NOT_ILIKE
CUSTOM
RAW
CUSTOM_EQUAL
DISTINCT
IN
NOT_IN
ALL
JOIN
BINARY_AND
BINARY_OR
ASC
DESC
ISNULL
ISNOTNULL
CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
LEFT_JOIN
RIGHT_JOIN
INNER_JOIN
LOGICAL_OR
LOGICAL_AND
Related
I need some help with a query as I don't seem to get my head around it.
First table vacancies:
vac_id
vac_title
vac_location
vac_description
is_deleted
status
Second table vacancies_labels:
vac_id
Label_id
Now I would like to get an output containing all vacancies within a certain location but they also cannot contain the label_id '10' nonetheless of the location.
SELECT `v`.*
FROM `vacancies` AS `v`
LEFT JOIN `vacancies_labels` as `vl` ON `v`.`vacancy_id` = `bl`.`vacancy_id`
WHERE `v`.`vac_location` = 'russia'
AND `v`.`is_deleted` != 1
AND `v`.`status` = 1
AND `vl`.`label_id` NOT IN ('10')
GROUP BY `v`.`vacancy_id`
This results only in the vacancies that have a record in the vacancies_labels table that are not 10. It leaves out however all vacancies that have no records at all in the vacancies_labels table but fit within the location range.
What am I missing here?
Thx!
Using a LEFT JOIN, if the record is not found, then the values will return null. But in your WHERE clause, you have
AND `vl`.`label_id` NOT IN ('10')
as NOT IN doesn't consider nulls you have to do something like...
AND ( `vl`.`label_id` NOT IN ('10') OR `vl`.`label_id` IS NULL)
I am using ST_Intersects() to know whether two geometries intersect or not.
This is my code:
$var_name = pg_query($conn,"SELECT ST_Intersects(p1.column_name,
p2.column_name)
FROM table_name AS p1, table_name AS p2
WHERE p1.id < p2.id");
if(pg_fetch_assoc($var_name) == 'false')
{
echo "accepted";
}
else
{
echo "rejected";
}
I know that the geometries are not intersecting and when I run the same query in Postgres the result is false as expected.
But here it is executing the else statement. Where am I wrong?
Erwin's advice is (as always) good, but in your particular case I think the problem is in your test.
if(pg_fetch_assoc($var_name) == 'false')
pg_fetch_assoc returns an associative array which you are comparing to a single string. Comparing mixed types is a complicated process in php, but in this case it knows that a string is not an array and so they aren't equal.
You probably want something like the following:
$row = pg_fetch_assoc($var_name)
if ($row['ST_Intersects'] == false)
Don't guess though, do something like print_r($row) to confirm you have the column-names and values you think you do.
The same query can return a different result every time you call it, since it's not deterministic. Any number of rows can qualify in each table, producing a Cartesian product of results. And since there is not unambiguous ORDER BY in your query, an arbitrary row will be the first to be returned.
Either add an ORDER BY (plus LIMIT 1) or more WHERE conditions to return a single row (deterministically).
Alternative query:
SELECT EXISTS (
SELECT 1
FROM table_name p1
JOIN table_name p2 ON p1.id < p2.id
WHERE ST_Intersects(p1.column_name, p2.column_name)
);
This returns exactly 1 row with true or false (never null, and never 0 or multiple rows). It's true if at least one combination intersects.
But also look to Richard's answer for the PHP part of the test.
I have a table like this:
table
- field1: tinyint
- field2: varchar (nullable)
- datefield: timestamp (nullable)
Now I want to get all entries where field1 is 1, field2 is null and where datefield is smaller than X or null. I already tried something like this:
$query = Model::where('field1', 1)
->whereNull('field2')
->where('datefield', '<', $date)
->orWhereNull('datefield');
but thats not working. I always get every entry where datefield is null. It doesn't matter what the other fields are. I also tried to split it in 2 queries: First get every row where datefield is smaller than X or null and then (based on it) get every field where field1 is 1 and field2 is null.
The result was the same.
Any idea how to do this?
It sounds like you need to make use of advanced where clauses.
Given that search in field1 and field2 is constant we will leave them as is, but we are going to adjust your search in datefield a little.
Try this:
$query = Model::where('field1', 1)
->whereNull('field2')
->where(function ($query) {
$query->where('datefield', '<', $date)
->orWhereNull('datefield');
}
);
If you ever need to debug a query and see why it isn't working, it can help to see what SQL it is actually executing. You can chain ->toSql() to the end of your eloquent query to generate the SQL.
You could merge two queries together:
$merged = $query_one->merge($query_two);
Using coalesce() converts null to 0:
$query = Model::where('field1', 1)
->whereNull('field2')
->where(DB::raw('COALESCE(datefield_at,0)'), '<', $date)
;
If you are confused about where to put the get()/first() for getting the collection or a single row here is the way:
$query = Model::where('field1', 1)
->whereNull('field2')
->where(function ($query) {
$query->where('datefield', '<', $date)
->orWhereNull('datefield');
}
)->get();
I have table with 10 columns and I want to check input value in where clause of the MySQL query.
I want to do something like this. But, when I use this query I am getting an error.
for example :
SELECT * FROM user_data
where poll_title='$poll_title'
and '$voter' IN (user_vote_1,user_vote_2,user_vote_3...user_vote_10)
order by idpoll ASC
user_vote_1 to 10 (value is null'ed in the database) and I want to retrieve only that rows from a column which have $voter value.
I think you need this comparison (Not Sure OfCourse) :-
SELECT * FROM user_data
where poll_title = "$poll_title"
and (user_vote_1 = "$voter"
OR user_vote_2 = "$voter"
OR user_vote_3 = "$voter"
OR user_vote_4 = "$voter"......OR user_vote_10 = "$voter")
order by idpoll ASC
If I've understood what you want to do - return only the column with the value - then would coalesce do the job? This assumes that the value in user_vote_n will either match the value you're looking for or be null, since coalesce returns the first non-null argument.
(untested)
select coalesce(user_vote_1, user_vote_2, user_vote_3, ) as UserVote from user_data
where coalesce(user_vote_1, user_vote_2, user_vote_3, ) = '$voter';
That aside, this looks like a structure that could do with normalising - a single 'user_vote' column and a single 'user_vote_number' column.
I have a database field know as SCORES which has Scores
the value may be like the following
123
14
56*
342
423*
I am storing that in a Varchar Field in the database.
Suppose If I convert that to a integer a datatype, then I can write
max(SCORES) and get the Maximum score or Highest Scores.
But Integer doesnot allow special character like *.
(Here * represent some clause for that scores)
To accomadate that I have made that to the varchar.
What will be best way to get the Highest score very easily with minimum programming method.
So that If I execute a query I should be get the answer as
423*
Please suggest me
The best way to handle this situation is to change you table structure to make
SCORES of int data type.
Add a new field in the table called
clause
If most of your SCORES are without a
clause, you must normalize the table
to move the clause field to a
different table.
You should change table schema ...
SELECT scores
FROM tablename
ORDER BY replace(scores, '*', '') DESC
LIMIT 1;
I think your query should be generic for getting maximum score, today you have only '*' is attached with score but in future may be you use some others character or may be you use some combination of character so you should take care of that scenario.
so i thing it will be better if you create a user define function which takes varchar as a input and return number from input string like if you pass '1234*' then function will return 1234 and if you pass 1234** it will return 1234.
CREATE FUNCTION dbo.ParseNumeric
(
#string VARCHAR(8000)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #IncorrectCharLoc SMALLINT
SET #IncorrectCharLoc = PATINDEX('%[^0-9A-Za-z]%', #string)
WHILE #IncorrectCharLoc > 0
BEGIN
SET #string = STUFF(#string, #IncorrectCharLoc, 1, '')
SET #IncorrectCharLoc = PATINDEX('%[^0-9]%', #string)
END
SET #string = #string
RETURN #string
END
GO
then use:
select max(cast(dbo.ParseNumeric(score) as int)) from tableName
SELECT MAX(CAST(scores AS SIGNED))
FROM tablename
But this query will be quite slow, since it cannot be optimized using indexes.
You could move the asterisk to a new field (depends if you need it or not). After that you can change the datatype.
UPDATE
tableName
SET
score = REPLACE(score, '*', ''),
specialCharField = IF(CONTAINS(score, '*'), '*', '');
Try this SQL:
SELECT MAX(CONVERT(REPLACE(FIELD,'*',''),signed)) FROM TABLE
It:
Replace the * from your varchar
Covnert the result into integer (signed)
Select the MAX value
EDIT 1:
I have been tring the SQL with some data, i have a table with one field (varchar, no key), I've inserted 62962 values (one each 1000 have a '*', the results as follow :)
SELECT MAX(CONVERT(REPLACE(FIELD,'*',''),signed)) FROM TABLE
Took 0.0666sec.
SELECT scores FROM tablename ORDER BY replace(scores, '*', '') DESC LIMIT 1;
Took 0.089sec to execute and got the wrong value:
HTH :)