mySQL Inclusive search on a flat table - mysql

I have the below SQL table, and i'm wondering if it's possible to have an inclusive search with this table format? Meaning if someone were to search for SSNU and ACCOUNT_NO it would only return the data if the CASE ID has an SSNU and ACCOUNT_NO that match the inputs.
I've tried a where clause like the below:
AND (a.KEY = "ACCOUNT_NO" AND a.VALUE = "XXXXXX")
AND (a.KEY = "GPID" AND a.VALUE = "XXXXX")
but have not had any luck.

Do you want to prioritize the row whose key is 'ACCOUNT_NO', and fallback on 'GPID'? If you want just one row, then you can use order by and limit:
select *
from mytable a
where a.key in ('ACCOUNT_NO', 'GPID') and a.value = 'XXXXXX'
order by a.key = 'ACCOUNT_NO' desc
limit 1
The order by clause puts first the row whose key is 'ACCOUNT_NO', if any. Note that I factorized the condition on VALUE, since it is common to both conditions.

If by "person" you mean "case id", then I think you want aggregation:
select case_id
from t
where (a.KEY = 'ACCOUNT_NO' AND a.VALUE = 'XXXXXX') or
(a.KEY = 'GPID' AND a.VALUE = 'XXXXX')
group by case_id
having count(distinct a.key) = 2;
This returns cases that have both the key/value pairs.

Related

How to use 'Mysql JOIN' with sql text of same table

I want to use mysql's "JOIN"
I want to group rows by "date_text" where "tokenIdx" is "1001" and "datetime_unix" is the highest value.
Is my code wrong?
SELECT `A.idx`
FROM `data_candle_h1` 'A'
JOIN
(
SELECT `date_text`, MAX(`datetime_unix`) AS 'datetime_unix'
FROM `data_candle_h1`
WHERE `tokenIdx` = '1002'
GROUP BY `date_text`
) 'B'
ON `A.datetime_unix` = `B.datetime_unix`
WHERE `A.tokenIdx` = '1002'
Your query is syntactically perfect. Just remove single quotes('') around table aliases (A and B). I have corrected it. Please check this out.
SELECT `A.idx`
FROM `data_candle_h1` A
JOIN
(
SELECT `date_text`, MAX(`datetime_unix`) AS 'datetime_unix'
FROM `data_candle_h1`
WHERE `tokenIdx` = '1002'
GROUP BY `date_text`
) B
ON `A.datetime_unix` = `B.datetime_unix`
WHERE `A.tokenIdx` = '1002'

Conditionally select from one table or another in MySQL

In MySQL, how do I select from another table if a foreign key is set?
What I'm trying to do is select Fields.value if Fields.value_id isn't set, otherwise select Values.value from Values where Value.id is equal to Fields.value_id.
My tables:
Fields:
id | value | value_id
Values:
id | value
What's wrong with my code here?
Code:
SELECT CASE
WHEN Field.value_id = NULL OR Field.value_id = ""
THEN Field.value
ELSE
Value.value
FROM values as Value
WHERE (Field.value_id = Value.id)
One syntax error is that you are missing the end in the case. I also think you want a left join between the tables. My best guess given the available information is this:
SELECT (CASE WHEN f.value_id = NULL OR f.value_id = ''
THEN f.value
ELSE v.value
END)
FROM fields f left join
values v
on f.value_id = v.id;

How to query mysql to select and group by multiple values

I'm trying to select and group by all the contentid values of the table below where the match criteria can be several different values.
the contentid values actually represent cars, so I need to select [and group by] all the contentis where the values are 'GMC' and the values are 'sedan' and the value is 'automatic.
i.e. I'm trying to select all the GMC sedans with an automatic transmission.
a query like this fails [obviously]:
select * from modx_site_tmplvar_contentvalues WHERE
`value` = 'gmc' and
`value` = 'tacoma'
group by contentid
I have no idea how to create a query like that. Any suggestions?
You need to "pivot" these data on "tmplvarid", but unfortunately for you MySQL doesn't have a PIVOT statement like other RDBMS. However, you can pivot it yourself by joining in the table multiple times for each variable you care about:
SELECT
contents.contentid,
transmission.value as transmission,
type.value as type,
make.value as make
FROM
(SELECT DISTINCT contentid FROM modx_site_tmplvar_contentvalues) AS contents
LEFT JOIN
modx_site_tmplvar_contentvalues AS transmission
ON contents.contentid = transmission.contentid
AND transmission.tmplvarid = 33 -- id for transmission
LEFT JOIN
modx_site_tmplvar_contentvalues AS make
ON contents.contentid = make.contentid
AND make.tmplvarid = 13 -- id for make
LEFT JOIN
modx_site_tmplvar_contentvalues AS type
ON contents.contentid = type.contentid
AND type.tmplvarid = 17 -- id for type
WHERE
type.value = 'sedan'
AND make.value = 'GMC'
AND transmission.value = 'automatic'
You can expand this with additional joins for other criteria such as year (id 15) or mileage (id 16).
If you need to use the value only, you could try:
SELECT DISTINCT
contents.contentid,
transmission.value as transmission,
type.value as type,
make.value as make
FROM
(SELECT DISTINCT contentid FROM modx_site_tmplvar_contentvalues) AS contents
INNER JOIN
modx_site_tmplvar_contentvalues AS transmission
ON contents.contentid = transmission.contentid
AND transmission.value = 'automatic'
INNER JOIN
modx_site_tmplvar_contentvalues AS make
ON contents.contentid = make.contentid
AND make.value = 'GMC'
INNER JOIN
modx_site_tmplvar_contentvalues AS type
ON contents.contentid = type.contentid
AND type.value = 'sedan'
In any case, make sure you have an index on the value column; these queries are going to get slow.
please try this:
SELECT *
FROM modx_site_tmplvar_contentvalues t1 INNER JOIN modx_site_tmplvar_contentvalues t2 ON t1.contentid = t2.content_id
WHERE
t1.`value` = 'gmc'
AND t2.`value` = 'tacoma';
You can do this with a group by. This is the most flexible in terms of expressing the conditions. In MySQL, multiple joins will often perform better:
select contentid
from modx_site_tmplvar_contentvalues
group by contentid
having sum(`value` = 'gmc') > 0 and
sum(`value` = 'tacoma') > 0;
This is always false:
`value` = 'gmc' and
`value` = 'tacoma'
Instead, use OR:
`value` = 'gmc' OR
`value` = 'tacoma'
In a condition "and" means "this and this is true at the same time". If you want all foos and all bars, then your condition is "foo OR bar".
EDIT:
To select groups containing your values, you can write subqueries:
SELECT DISTINCT name FROM table WHERE name IN (SELECT name FROM table WHERE value='value1') AND name IN (SELECT name FROM table WHERE value='value2')

Assign a value to a field on SELECT statement

im not sure if im doing well with this field calendar.type_event = NULL. Now works well to me because I need to differentiate the second SELECT as a third type.
I want to do something like calendar.type_event = 'shared_event' to differentiate it. But returns a 0, with NULL returns nothing. This is not the problem only I need to know if I can assign my own value: 'shared_event'.
Thanks a lot
The entire query is:
(SELECT
id, type_event
FROM calendar
WHERE user_id = '.$user_id.'
)
UNION
(SELECT
calendar.id, calendar.type_event = NULL
FROM calendar
RIGHT JOIN avisos ON avisos.app_id = calendar.id
WHERE avisos.user_destiny_id = '.$user_id.'
)
ORDER BY fecha_evento ASC
I need to know if I can assign my own value: 'shared_event'.
Yes, you can. In place of column calendar.type_event just use literal 'shared_event'
Example:
SELECT
calendar.id, 'shared_event'
FROM calendar
RIGHT JOIN avisos ON avisos.app_id = calendar.id
WHERE avisos.user_destiny_id = '.$user_id.'
You should be able to do something like this:
(SELECT
id, type_event
FROM calendar
WHERE user_id = '.$user_id.'
)
UNION
(SELECT
calendar.id, "shared_event"
FROM calendar
RIGHT JOIN avisos ON avisos.app_id = calendar.id
WHERE avisos.user_destiny_id = '.$user_id.'
)
ORDER BY fecha_evento ASC
I think this is what you are looking for:
(SELECT
id, type_event
FROM calendar
WHERE user_id = '.$user_id.'
)
UNION
(SELECT
calendar.id, '' type_event
FROM calendar
RIGHT JOIN avisos ON avisos.app_id = calendar.id
WHERE avisos.user_destiny_id = '.$user_id.'
)
ORDER BY fecha_evento ASC
In the second query, type_event field will contain null values. If the type_event field is a numeric field, you can put 0 (ZERO) instead of '' (empty single quotes/string).

MySQL: how can I count number of articles by a join table

I have a table with news items, I have another table with media_types, I want to make one simple query that reads the media_types table and count for each record how many news_items exist.
The result will be turned into a json response that I will use for a chart, this is my SQLstatement
SELECT
gc.country AS "country"
, COUNT(*) AS "online"
FROM default_news_items AS ni
JOIN default_news_item_country AS nic ON (nic.id = ni.country)
JOIN default_country AS c ON (nic.country = c.id)
JOIN default_geo_country AS gc ON (gc.id = c.geo_country)
LEFT JOIN default_medias ON (m.id = ni.media)
WHERE TRUE
AND ni.deleted = 0
AND ni.date_item > '2013-10-23'
AND ni.date_item < '2013-10-29'
AND gc.country <> 'unknown'
AND m.media_type = '14'
GROUP BY gc.country
ORDER BY `online` desc LIMIT 10
This is the json respond I create from the mysql respond
[
{"country":"New Zealand","online":"7"},
{"country":"Switzerland","online":"1"}
]
How do I add print and social data to my output like this
I would like the json respond look like this
[
{"country":"New Zealand","online":"7", "social":"17", "print":"2"},
{"country":"Switzerland","online":"1", "social":"7", "print":"1"}
]
Can I use the count (*) in the select statement to do something like this
COUNT( * ) as online, COUNT( * ) as social, COUNT( * ) as print
Is it possible or do I have to do several SQL statement to get the data I'm looking for?
This is the general structure:
SELECT default_geo_country.country as country,
SUM(default_medias.media_type = 14) as online,
SUM(default_medias.media_type = XX) as social,
SUM(default_medias.media_type = YY) as print
FROM ...
JOIN ...
WHERE ...
GROUP BY country
I think you want conditional aggregation. Your question, however, only shows the online media type.
Your query would be more readable by using table aliases and removing the back quotes. Also, if media_type is an integer, then you should not enclose the constant for comparison in single quotes -- I, for one, find it misleading to compare a string constant to an integer column.
I suspect this is the way you want to go. Where the . . . is, you want to fill in with the counts for the other media types.
SELECT default_geo_country.country as country,
sum(media_type = '14') as online,
sum(default_medias.media_type = XX) as social,
sum(default_medias.media_type = YY) as print
. . .
FROM default_news_items ni JOIN
default_news_item_country nic
ON nic.id = ni.country JOIN
default_country dc
ON nic.country = dc.id JOIN
default_geo_country gc
ON gc.id = dc.geo_country LEFT JOIN
default_medias dm
ON dm.id = dni.media
WHERE ni.deleted = '0'
AND ni.date_item > '2013-10-23'
AND ni.date_item < '2013-10-29'
AND gc.country <> 'unknown'
GROUP BY gc.country
ORDER BY online desc
LIMIT 10