So I have 3 SQL query results (example code below). I want the results to be displayed either as different columns or different tables. Is this even possible? If yes, please help as to how. The results are unrelated to each other
SELECT RouterName, RouterType, Loopback100, Loopback200, ResiliencyGroup,
DeploymentStatus
FROM Routers
WHERE RouterName = 'PE23-SNG-AP'
SELECT ARouter, AInterface, BRouter, BInterface
FROM netplan.LinksPACSLcl
WHERE ARouter = 'PE23-SNG-AP' OR Brouter = 'PE23-SNG-AP'
This is, I believe, a job for JOIN. With respect if you don't know about JOIN you should study it; it's a core feature of SQL. It combines rows from multiple tables into single output rows.
Try something like this
SELECT i.RouterName, i.RouterType, i.Loopback100, i.Loopback200,
i.ResiliencyGroup i.DeploymentStatus,
j.ARouter, j.AInterface, j.BRouter, j.BInterface
FROM Routers i
LEFT JOIN netplan.LinksPACSLcl j (ON i.RouterName = j.ARouter
OR i.RouterName = j.BRouter)
WHERE RouterName = 'PE23-SNG-AP'
This generates a result set with the items from both your first and second tables, assiging the alias names i and j to those tables. The LEFT JOIN operation allows information from the first table to be shown even without anything matching it in the second table.
You should use UNION. This is a working sample. The important part is Column names. Check carefully the usage of col1 with as
select UserName as col1 from Users
union
select FeatureName as col1 from Features
union
select TopicName as col1 from Topics
If you can accept a json result ;)
SELECT JSON_ARRAY_APPEND('[]', '$',
JSON_EXTRACT((SELECT concat('[',
group_concat(
JSON_OBJECT('RouterName' , `RouterName`,
'RouterType' , `RouterType`,
'Loopback100' , `Loopback100`,
'Loopback200' , `Loopback200`,
'ResiliencyGroup' , `ResiliencyGroup`,
'DeploymentStatus', `DeploymentStatus`)
SEPARATOR ','),
']')
FROM Routers
WHERE RouterName = 'PE23-SNG-AP'), '$[*]'), '$',
JSON_EXTRACT((SELECT concat('[',
group_concat(
JSON_OBJECT('ARouter' , `ARouter`,
'AInterface', `AInterface`,
'BRouter' , `BRouter`,
'BInterface', `BInterface`)
SEPARATOR ','),
']')
FROM netplan.LinksPACSLcl
WHERE ARouter = 'PE23-SNG-AP'
OR Brouter = 'PE23-SNG-AP'), '$[*]'));
If you use sql server, you can use SELECT ... FOR XML RAW...
https://learn.microsoft.com/en-us/sql/relational-databases/xml/example-specifying-a-root-element-for-the-xml-generated-by-for-xml
Related
I'm working through MySQL connector in python on a project where I'm analyzing books.
I would gladly accept any help with my issue (explained below).
The relevant DB structures:
each Word, in each book, has its own word_id(primary key) and text.
each Word_instance has word_id, word_serial, offset in line, sentence number and so on...
the entity Word_instance's word_serial is its offset from the beginning of the book.
each Phrase has its own id and text.
each Phrase_word has phrase_id and word_id(from above).
Right now, I'm trying to figure out how to build a query that will locate a phrase from the user in the database.
Words are a part of a phrase if they have consecutive word_serial and are in the same sentence.
so far I've managed to build the following mess of a query:
select book_id
, word_txt
, word_serial
, sentence_serial
, ROW_NUMBER() Over (partition by sentence_serial, book_id) as encounter_num
from word
join word_instance
on word.word_id = word_instance.word_id
join word_in_phrase
on word.word_id = word_in_phrase.word_id
where phrase_id = %s
order
by book_id
, sentence_serial
, word_serial
In the following table image is the result set of said query.
let's say the user has entered the phrase: "I believe in cause".
in that case I would need to extract word_serial = 562, as it is the beginning said phrase.
can I accomplish such a task without extracting row by row and assessing whether the current row is part of the phrase and in the correct order?
In fact, there are way to many rows to examine outside of SQL to consider that a possibility.
I will appreciate your help immensely, as I'm stuck on this issue for far too long...
As requested, I'm uploading images of relevant DB entities:
Word_in_phrase entity
Word_instance entity
word entity
This probably isn't the most efficient way of writing this, but I think it works in principle and you could tinker with it as you wanted. Note that I assumed phrases can't cross sentence boundaries (wi2.sentence_serial = wi1.sentence_serial) and I've assumed a column word_in_phrase.order_id exists that starts at 0 and increases by 1 for each word. I'm also assuming word_id increases by 1 each row. (You could make those assumptions true by using CTEs where that is true instead of the real tables).
with (
SELECT *
FROM word_in_phrase
WHERE phrase_id = %s
) as phrase
select book_id
, word_txt
, word_serial
, sentence_serial
from word
join word_instance wi1
on word.word_id = word_instance.word_id
where (SELECT COUNT(*) FROM phrase) = (SELECT COUNT(*) FROM word_instance wi2 INNER JOIN phrase on wi2.word_id = phrase.word_id WHERE wi2.book_id = wi1.book_id and wi2.sentence_serial = wi1.sentence_serial and wi2.word_id = wi1.word_id + phrase.order_id)
order
by book_id
, sentence_serial
, word_serial
Alternatively, you might prefer something like
with (
SELECT *
FROM word_in_phrase
WHERE phrase_id = %s
) as phrase
select wi1.book_id
, word_txt
, wi1.word_serial
, wi1.sentence_serial
from word
join word_instance wi1
on word.word_id = word_instance.word_id
inner join word_instance wi2
on wi2.book_id = wi1.book_id and wi2.sentence_serial = wi1.sentence_serial
INNER JOIN phrase
on wi2.word_id = phrase.word_id
WHERE wi2.word_id = wi1.word_id + phrase.order_id
GROUP BY
wi1.book_id
, word_txt
, wi1.word_serial
, wi1.sentence_serial
HAVING COUNT(*) = (SELECT COUNT(*) FROM phrase)
my first query :
SELECT `oc_banner_image_description`.`title`
FROM `oc_banner_image_description`
WHERE `banner_id`=9
my second query:
SELECT `oc_banner_image`.`image` FROM `oc_banner_image` WHERE `banner_id`=9
how to make this two queries into single query using sql joins.
Using standard join syntax would look like this :
SELECT `oc_banner_image_description`.`title`, `oc_banner_image`.`image`
FROM `oc_banner_image_description`
JOIN `oc_banner_image` ON `oc_banner_image_description`.`banner_id` = `oc_banner_image`.`banner_id`
WHERE `oc_banner_image`.`banner_id`=9
Try this (You may need to use the single quotes a bit different than what I have)
SELECT `i`.`image`, `d`.`title`
FROM `oc_banner_image` as `i`, `oc_banner_image_description` as `d`
WHERE `c.banner_id` = `i.banner_id`
and i.`banner_id`=9
If this is not working try this on both tables
select banner_id, count(banner_id)
from oc_banner_image
group by banner_id order desc;
This will tell you if you have multiple banner_id's in the oc_banner_image table.
Try this
SELECT bannerDesc.title , bannerImage.image
FROM oc_banner_image_description bannerDesc join oc_banner_image bannerImage
on bannerDesc.banner_id = bannerImage.banner_id
WHERE bannerImage.banner_id=9
I am trying to do an INNER JOIN on two tables that have similar values, but not quite the same. One table has a fully qualified host name for its primary key, and the other the hosts short name, as well as the subdomain. It it safe to assume that the short name and the subdomain together are unique.
So I've tried:
SELECT table1.nisinfo.* FROM table1.nisinfo INNER JOIN table2.hosts ON (table1.nisinfo.shortname + '.' + table1.nisinfo.subdomainname + '.domain.com') = table2.hosts.fqhn WHERE table2.hosts.package = 'somepkg';
This doesn't return the results I expect, it returns the first result hundreds of times. I'd like to return distinct rows. It takes a long time to run as well.
What am I doing wrong? I was thinking of running a subquery to get the hostnames, but I don't know what the right path from here is.
Thank you!
You can use group by in your query so you can achieve the desired results you want
please see this two links
Group by with 2 distinct columns in SQL Server
http://www.sqlteam.com/article/how-to-use-group-by-with-distinct-aggregates-and-derived-tables
Try putting your results into a temp table and then view the table to make sure that the columns are as expected.
SELECT table1.nisinfo.*, table1.nisinfo.shortname + '.' + table1.nisinfo.subdomainname + '.domain.com' AS ColID
INTO #temp
FROM table1.nisinfo;
Select *
from #temp INNER JOIN table2.hosts ON ##temp.ColID = table2.hosts.fqhn
WHERE table2.hosts.package = 'somepkg'
;
Put a Group By clause at the end of the second statement
So in this case, I used a subquery to get the initial results, and then used a join.
SELECT table1.nisinfo.* FROM table1.nisinfo JOIN (SELECT distinct(fqhn) FROM table2.hosts WHERE package = 'bash') AS FQ ON ((SUBSTRING_INDEX(FQ.fqhn, '.', 1)) = table1.nisinfo.shortname);
I have a little query, it goes like this:
It's slightly more complex than it looks, the only issue is using the output of one subquery as the parameter for an IN clause to generate another. It works to some degree - but it only provides the results from the first id in the "IN" clause. Oddly, if I manually insert the record ids "00003,00004,00005" it does give the proper results.
What I am seeking to do is get second level many to many relationship - basically tour_stops have items, which in turn have images. I am trying to get all the images from all the items to be in a JSON string as 'item_images'. As stated, it runs quickly, but only returns the images from the first related item.
SELECT DISTINCT
tour_stops.record_id,
(SELECT
GROUP_CONCAT( item.record_id ) AS in_item_ids
FROM tour_stop_item
LEFT OUTER JOIN item
ON item.record_id = tour_stop_item.item_id
WHERE tour_stop_item.tour_stops_id = tour_stops.record_id
GROUP BY tour_stops.record_id
) AS rel_items,
(SELECT
CONCAT('[ ',
GROUP_CONCAT(
CONCAT('{ \"record_id\" : \"',record_id,'\",
\"photo_credit\" : \"',photo_credit,'\" }')
)
,' ]')
FROM images
WHERE
images.attached_to IN(rel_items) AND
images.attached_table = 'item'
ORDER BY img_order ASC) AS item_images
FROM tour_stops
WHERE
tour_stops.attached_to_tour = $record_id
ORDER BY tour_stops.stop_order ASC
Both of these below answers I tried, but it did not help. The second example (placing the entire first subquery inside he "IN" statement) not only produced the same results I am already getting, but also increased query time exponentially.
EDIT: I replaced my IN statement with
IN(SELECT item_id FROM tour_stop_item WHERE tour_stops_id = tour_stops.record_id)
and it works, but it brutally slow now. Assuming I have everything indexed correctly, is this the best way to do it?
using group_concat in PHPMYADMIN will show the result as [BLOB - 3B]
GROUP_CONCAT in IN Subquery
Any insights are appreciated. Thanks
I am surprised that you can use rel_items in the subquery.
You might try:
concat(',', images.attached_to, ',') like concat('%,', rel_items, ',%') and
This may or may not be faster. The original version was fast presumably because there are no matches.
Or, you can try to change your in clause. Sometimes, these are poorly optimized:
exists (select 1
from tour_stop_item
where tour_stops_id = tour_stops.record_id and images.attached_to = item_id
)
And then be sure you have an index on tour_stop_item(tour_stops_id, item_id).
This small SQL error is bugging me. It doesn't seem to be a problem with the query, just the scope(?), examples work best:
SELECT ocp.*, oc.*, GROUP_CONCAT( u.username SEPARATOR ', ') AS `memjoined`
FROM gangs_ocs_process ocp, gangs_ocs oc
LEFT JOIN users u ON u.userid IN ( ocp.membersin )
WHERE ocp.ocid =1 AND ocp.gangid =1 AND oc.oc_name = ocp.crimename
GROUP BY ocp.ocid
LIMIT 0 , 30
Theres a column (gangs_ocs_process.membersin) which has a list of IDs that have joined (ie 1,2,5). I'm trying to get the usernames for each of these IDs (from the users table) in one go.
The problem is LEFT JOIN users u ON u.userid IN ( ocp.membersin )
If I substitue 1,2,4 in for ocp.membersin (putting the literal list instead of column name), it works ok. It returns a column that has the usernames (image). However, if I leave in the ocp.membersin, I get this error:
#1054 - Unknown column 'ocp.membersin' in 'on clause'
This is the first time I've even used IN in left joins so I'm a bit lost.
Any help would be great :)
I don't think that "IN" will work for this syntax. MySQL expects IN to be something akin to a dataset, not a delimited string. I think you need to find a way to take membersin, expand it into a dataset MySQL can work with (maybe a temporary table), and join on that.
If you have delimited strings in your table, you have a design problem in your database. Add a new table to hold these values.
Are you sure 'membersin' is in the 'gangs_ocs_process' table, and not the 'gangs_ocs' table?
The reason you can't get it to work is because first you need to get your database NORMALIZED. You should NEVER, EVER have a list of ID's in a single column.
After taking another look, I think your problem is trying to aggregate at the wrong point as well as the IN syntax and that you should aggregate in a subquery restricted by the contents of the IN. I don't know enough about your schema to make this out of the box correct, but you want something like this. SomeKeyfield should relate back to gangs_ocs_process
SELECT ocp.*, oc.*, u.Memjoined
FROM gangs_ocs_process ocp, gangs_ocs oc
LEFT JOIN (Select SomeKeyField, GROUP_CONCAT( u.username SEPARATOR ', ') as memjoined
from users where userid in
(select membersin from gangs_ocs_process
where [whatever conditions] )
Group By SomeKeyField) u on ocp.SomeKeyField = u.SomeKeyField
WHERE ocp.ocid =1 AND ocp.gangid =1 AND oc.oc_name = ocp.crimename
GROUP BY ocp.ocid
LIMIT 0 , 30
This is a bad way to keep membership.
But if you still need to live with it, you may try REGEXP matching to test for membership:
SELECT ocp.*, oc.*, GROUP_CONCAT( u.username SEPARATOR ', ') AS `memjoined`
FROM gangs_ocs_process ocp
LEFT JOIN users u ON (ocp.membersin RLIKE CONCAT('(^|,)[[:blank:]]?', userid, '[[:blank:]]?($|,)'))
JOIN gangs_ocs oc ON (ocp.ocid = 1 AND ocp.gangid = 1 AND oc.oc_name = ocp.crimename)
GROUP BY ocp.ocid
LIMIT 0 , 30