Assistance with SELECT - mysql

I have three tables: hosting_pack, hosting_attr and hosting_attr_value.
One hosting_category can have many hosting_packs and many hosting_attributes.
To know the hosting_value, we must know the hosting_pack and the hosting_attribute, so hosting_pack contains the pack information, hosting_attr contains the attributes, and hosting_attr_value contains the values of every attribute in one pack.
Described as follows :
I want to display a table like this:
hosting_attr, hosting_attr_value , for a given id_hosting_pack
Note: the relation between hosting_categ and hosting_attr doesn't exist, just ignore it.

Try this:
select hosting_attr.attr_label, hosting_attr_value.hosting_attr_value from hosting_attr_value, hosting_attr where hosting_attr_value.id_hosting_pack = ? and hosting_attr.id_hosting_attr = hosting_attr_value.id_hosting_attr
If you do not know id_hosting_pack, you can look it up in-line
select hosting_attr.attr_label, hosting_attr_value.hosting_attr_value from hosting_attr_value, hosting_attr where hosting_attr_value.id_hosting_pack = (select id_hosting_pack from hosting_pack where pack_name = ?) and hosting_attr.id_hosting_attr = hosting_attr_value.id_hosting_attr

select ha.attr_label, hav.attr_value from hosting_attr ha
inner join hosting_attr_value hav on ha.id_hosting_attr = hav.id_hosting_attr
where hav.id_hosting_pack = :theIdOfTheHostingPack

Try:
select *
from
hosting_pack hp,
hosting_attr_value hav,
hosting_attr ha
where
hp.id_hosting_pack = hav.id_hosting_pack
and hav.id_hosting_attr = ha.id_hosting_attr
Was that it?
And also try to study SQL a little bit.

Related

Use select filed result on LEFTJOIN string

I'm trying to use id_program result from the availability table inside a string in LEFTJOIN, is it possible?
I tried using this {post.id_program} but its not working.
SELECT *
FROM availability post
LEFT JOIN postmeta meta5 ON meta5.post_id = post.id_post
AND meta5.meta_key = 'items_iti_port_{post.id_program}_nights_iti_port'
WHERE post.id_post=462
EDIT:
http://sqlfiddle.com/#!9/aeb4a7/3
I see two ways..
Using CONCAT():
meta5.meta_key = CONCAT('items_iti_port_', post.id_program, '_nights_iti_port')
With REPLACE():
meta5.meta_key = REPLACE('items_iti_port_%_nights_iti_port', '%', post.id_program)

How to create union of two different django-models?

I have two django-models
class ModelA(models.Model):
title = models.CharField(..., db_column='title')
text_a = models.CharField(..., db_column='text_a')
other_column = models.CharField(/*...*/ db_column='other_column_a')
class ModelB(models.Model):
title = models.CharField(..., db_column='title')
text_a = models.CharField(..., db_column='text_b')
other_column = None
Then I want to merge the two querysets of this models using union
ModelA.objects.all().union(ModelB.objects.all())
But in query I see
(SELECT
`model_a`.`title`,
`model_a`.`text_a`,
`model_a`.`other_column`
FROM `model_a`)
UNION
(SELECT
`model_b`.`title`,
`model_b`.`text_b`
FROM `model_b`)
Of course I got the exception The used SELECT statements have a different number of columns.
How to create the aliases and fake columns to use union-query?
You can annotate your last column to make up for column number mismatch.
a = ModelA.objects.values_list('text_a', 'title', 'other_column')
b = ModelB.objects.values_list('text_a', 'title')
.annotate(other_column=Value("Placeholder", CharField()))
# for a list of tuples
a.union(b)
# or if you want list of dict
# (this has to be the values of the base query, in this case a)
a.union(b).values('text_a', 'title', 'other_column')
In SQL query, we can use NULL to define the remaining columns/aliases
(SELECT
`model_a`.`title`,
`model_a`.`text_a`,
`model_a`.`other_column`
FROM `model_a`)
UNION
(SELECT
`model_b`.`title`,
`model_b`.`text_b`,
NULL
FROM `model_b`)
In Django, union operations needs to have same columns, so with values_list you can use those specific columns only like this:
qsa = ModelA.objects.all().values('text_a', 'title')
qsb = ModelB.objects.all().values('text_a', 'title')
qsa.union(qsb)
But there is no way(that I know of) to mimic NULL in union in Django. So there are two ways you can proceed here.
First One, add an extra field in your Model with name other_column. You can put the values empty like this:
other_column = models.CharField(max_length=255, null=True, default=None)
and use the Django queryset union operations as described in here.
Last One, the approach is bit pythonic. Try like this:
a = ModelA.objects.values_list('text_a', 'title', 'other_column')
b = ModelB.objects.values_list('text_a', 'title')
union_list = list()
for i in range(0, len(a)):
if b[i] not in a[i]:
union_list.append(b[i])
union_list.append(a[i])
Hope it helps!!

Update table from View

I have the following view called cont_struct_breaks:
pipe_segment_reference com_struct_score com_defects com_struct_index
2610 353 111 3.2
3988 266 97 2.7
5632 49 22 2.2
I have another table called structural_rating with fields
pipe_segment_reference, structural_score structural_defects, structural_index
I want to UPDATE values in "structural_rating" from "cont_struct_breaks" WHERE the pipe_segment_reference matches.
I cannot figure this out however, I tired doing something like this but no luck.
Attempted This
[EDIT]
The cont_struct_breaks view is create with a select statement which looks like this:
SELECT
structural_rating.Pipe_Segment_Reference,
cont_struct + structural_score AS com_struct_score,
cont_struct_d + structural_defects AS com_defects,
ROUND(com_struct_score / com_defects, 1) AS com_struct_index
FROM ...
UPDATE structural_ratings table from the select statement above if easier than the view.
Doing a straight-up replace of your info for what's in the answer at that linked answer, I got this:
UPDATE
structural_rating
SET
structural_rating.structural_score = RAN.com_struct_score
FROM
structural_rating SI
INNER JOIN
cont_struct_breaks RAN
ON
SI.pipe_segment_reference = RAN.pipe_segment_reference
You'll probably want to change the names of the aliases to reduce confusion, but it'll work just fine the way it is.
So now you want to update additional fields. When you update multiple fields at once, you just separate them with commas:
SET
structural_rating.structural_score = RAN.com_struct_score,
structural_rating.structural_defects = RAN.com_defects,
structural_rating.structural_index = RAN.com_struct_index
So, your complete query should be:
UPDATE
structural_rating
SET
structural_rating.structural_score = RAN.com_struct_score,
structural_rating.structural_defects = RAN.com_defects,
structural_rating.structural_index = RAN.com_struct_index
FROM
structural_rating SI
INNER JOIN
cont_struct_breaks RAN
ON
SI.pipe_segment_reference = RAN.pipe_segment_reference
I ended up doing this writing to new table instead of view then running this:
UPDATE structural_rating
INNER JOIN cont_struct
ON structural_rating.pipe_segment_reference = cont_struct.pipe_segment_reference
SET
structural_score = cont_struct.com_struct_score,
structural_defects = cont_struct.com_defects,
structural_index = cont_struct.com_struct_index;

Yii2 query condition with exists

I have a simple Person tree with parent_id.
I wont to build a (Yii2) query to find all children of a given Person, that are parent of someone else (a.k.a not leaves).
The output SQL should looks like this:
select * from person t
where exists (select 1 from person p2 where t.id = p2.parent_id);
But cant find the right way to build this with the query builder, there is a method ->exists(), but not much documentation/examples about it.
Not sure if i understood correctly, but do you look something like this.
$subQuery = (new \yii\db\Query)
->select([new \yii\db\Expression('1')])
->from('person p2')
->where('t.id = p2.parent_id');
$query = (new \yii\db\Query())
->select('*')
->from('person t')
->where(['exists', $subQuery]);
$command = $query->createCommand();
print_r ($command->sql);
Generates sql like:
SELECT * FROM `person` `t` WHERE EXISTS (SELECT 1 FROM `person` `p2` WHERE t.id = p2.parent_id)
You should try something like :
$tableName = Person::tableName();
$subQuery = (new Query())->select('*')->from($tableName . ' t2')->where('t1.id=t2.parent_id');
$persons = Person::find()->from($tableName . ' t1')->where(['exists', $subQuery])->all();
http://www.yiiframework.com/doc-2.0/guide-db-query-builder.html#where
I don't know the right way with only queries, but if you use PHP also, then I think this will help you.
And also try to search in Google with keywords: hierarchical menu PHP

IF condition in mysql

I have a contact table I wish to query when a certain condition exists. I tried the query below but am getting a syntax error.
SELECT *
FROM contact_details
WHERE contactDeleted` =0
AND IF ( contactVisibility = "private"
, SELECT * FROM contact_details
WHERE contactUserId = 1
, IF( contactVisibility = "group"
, SELECT * FROM contact_details
WHERE contactGroup = 3
)
)
If I'm understanding your question correctly (which is difficult with the lack of info you've provided. Sample datasets and expected outcomes are typically helpful), then I don't believe you need IFs at all for what you want. The following will return contacts that are not deleted and who either have (visibility = "private" and userId = 1) OR (visibility = "group" and group = 3)
SELECT *
FROM contact_details
WHERE contactDeleted = 0
AND (
(contactVisibility = "public")
OR
(contactVisibility = "private" AND contactUserId = 1)
OR
(contactVisibility = "group" AND contactGroup = 3)
)
I am assuming you want to use the IF() function and not the statement which is for stored functions..
Refer to this link for more information on that.
Notice that you have put 2 select statements in there, where the custom return values are supposed to be. So you are returning a SELECT *... now notice that in your upper level sql statement you have an AND.. so you basically writing AND SELECT *.. which will give you the syntax error.
Try using .. AND x IN (SELECT *) .. to find if x is in the returned values.
Let me also list this link to make use of an existing and well written answer which may also applicable to your question.