Select Union in SphinxQL? - union

Is it possible to do any sort of Union using SphinxQL? I want to return one set of results containing two queries and in order of the query. A simple example would be:
Select Author from idx_jobs where MATCH('#(Author) Steinbeck')
Union Select Author from idx_jobs where MATCH('#(Description) Steinbeck')
Naturally I could do
Select Author from idx_jobs where MATCH('#(Author, Description) Steinbeck')
but I'm trying to provide some control over 'relevance' in the results.

No union.
But seems like field weight would be useful
http://sphinxsearch.com/docs/current.html#sphinxql-select
.... OPTION field_weights=(author=1000)
Should put the matches against the author field first. (ie add that to end of second query)

Related

Need to Add Values to Certain Items

I have a table that I need to add the same values to a whole bunch of items
(in a nut shell if the item doesn't have a UNIT of "CTN" I want to add the same values i have listed to them all)
I thought the following would work but it doesn't :(
Any idea what i am doing wrong ?
INSERT INTO ICUNIT
(UNIT,AUDTDATE,AUDTTIME,AUDTUSER,AUDTORG,CONVERSION)
VALUES ('CTN','20220509','22513927','ADMIN','AU','1')
WHERE ITEMNO In '0','etc','etc','etc'
If I understand correctly you might want to use INSERT INTO ... SELECT from original table with your condition.
INSERT INTO ICUNIT (UNIT,AUDTDATE,AUDTTIME,AUDTUSER,AUDTORG,CONVERSION)
SELECT 'CTN','20220509','22513927','ADMIN','AU','1'
FROM ICUNIT
WHERE ITEMNO In ('0','etc','etc','etc')
The query you needs starts by selecting the filtered items. So it seems something like below is your starting point
select <?> from dbo.ICUNIT as icu where icu.UNIT <> 'CTN' order by ...;
Notice the use of schema name, terminators, and table aliases - all best practices. I will guess that a given "item" can have multiple rows in this table so long as ICUNIT is unique within ITEMNO. Correct? If so, the above query won't work. So let's try slightly more complicated filtering.
select distinct icu.ITEMNO
from dbo.ICUNIT as icu
where not exists (select * from dbo.ICUNIT as ctns
where ctns.ITEMNO = icu.ITEMNO -- correlating the subquery
and ctns.UNIT = 'CTN')
order by ...;
There are other ways to do that above but that is one common way. That query will produce a resultset of all ITEMNO values in your table that do not already have a row where UNIT is "CTN". If you need to filter that for specific ITEMNO values you simply adjust the WHERE clause. If that works correctly, you can use that with your insert statement to then insert the desired rows.
insert into dbo.ICUNIT (...)
select distinct icu.ITEMNO, 'CTN', '20220509', '22513927', 'ADMIN', 'AU', '1'
from ...
;

Order by in union clause

Could any one please help me I have been working on a query containing unions n joins of multiple tables.. I have got the desired results but I want to get these results in some specific order so the whole result is being orderd according to one column.
Here is the snippet of code I am working on:
select name, age
from UserUni
order by age
union all
select age, Name
from UserOffice
order by age
Just add an ORDER BY clause at the very end of the UNION query, and it should be applied to the entire query:
select name, age
from UserUni
union all
select name, age
from UserOffice
order by age
Note that I swapped the order of the columns appearing in the second half of the UNION query because it doesn't make sense to put age and name into the same column. It is generally a requirement in a UNION query that the types and number of all columns be the same in boths halves of the query. One exception might be MySQL, which might appear to allow mixing numbers and text, but even in this case some implicit type conversion would be happening underneath the hood.
when we are using we can not use order by with both statements. because union at the end give one result end so how is it possible to use two order by statements.
you can check details here.
https://finalcodingtutorials.blogspot.ae/2017/03/order-by-clause-with-union-in-sql-server.html
hopefully it will resolve your issue will let you know complete details or union and order by statement.

Alias names in union / union all query - SQL Server

I have a simple sql statements as below
CASE 1:
select 1 as a
union
select 2 as a
Output: This case is working as expected
CASE 2:
select 1 as a
union
select 2 as b
Output: Though the alias is 'b' in my second select, it still shows the alias 'a'.
Why cant it take the alias from the second select statement?
How can we make sql to choose the alias from the second select query?
CASE 3:
select 1
union
select 2 as b
Output: Even though my first select statement above does not have any alias name but the second one still have, why the result still shows 'No column name'?
Lets try to teach something useful here. It is not just It's because that's how it is. There is a pattern definition that stipulate the rules for the SQL language and it is called SQL ANSI. You can see a timeline of this definition here: Database Administration - ANSI SQL Standards and Guidelines
The reason behind this definition is simple to understand. Since a UNION operation transform the result of two queries into one, some rules must be applied like the definition of the fields name, the types of the fields (in order they are select) and some others.
The alias part works just for the first one because there is no way for the database to identify which column would be the right one in a union operation as you will get one row per result:
select 1 as a
UNION
select 2
This will result in:
a
1
2
Since it is showed as ROWS how the database would work if it name each column for each SQL in the UNION stack?
-a
1
-b
2
That's why the rule of the first query alias is applied.
The SQL ANSI document is not free although if you dig enough you may find earlier versions of it in PDF. Good luck with that :) (hint: I have an answer in my profile with a working link ;) )
You could wrap everything around a single SELECT and alias that column with what you want.
select a as [b] -- just alias it here with whatever you want
from (
select 1 as a
union
select 2 as b
...) result_set
But as #Will said, it is what it is, can't change that.
OR:
Just make sure that you use the query with the "alias" that you want at the top and UNION that with a single SELECT statement that contains other queries / values you have.
select 2 as b
union
select a
from (
select 1 as a
union
select 3 as c
union
... ) result_set

Grouping by single column but returning all the columns without including other columns in aggregate function

I am working on an SQL query which should group by a column bidBroker and return all the columns in the table.
I tried it using the following query
select Product,
Term,
BidBroker,
BidVolume,
BidCP,
Bid,
Offer,
OfferCP,
OfferVolume,
OfferBroker,
ProductID,
TermID
from canadiancrudes
group by BidBroker
The above query threw me an error as follows
Column 'canadiancrudes.Product' is invalid in the select list because it is not contained in either an aggregate function or the
GROUP BY clause.
Is there any other way which returns all the data grouping by bidBroker without changing the order of data coming from CanadadianCrudes?
First if you are going to agregate, you should learn about agregate functions.
Then grouping becomes much more obvious.
I think you should explain what you are trying to accomplish here, because I suspect that you are trying to SORT bu Bidbroker, rather than grouping.
If you mean you want to sort by BidBroker, you can use:
SELECT Product,Term,BidBroker,BidVolume,BidCP,Bid,Offer,OfferCP,OfferVolume,OfferBroker,ProductID,TermID
FROM canadiancrudes
ORDER BY BidBroker
If you want to GROUP BY, and give example-data you can use:
SELECT c1.Product,c1.Term,c1.BidBroker,c1.BidVolume,c1.BidCP,c1.Bid,c1.Offer,c1.OfferCP,c1.OfferVolume,c1.OfferBroker,c1.ProductID,c1.TermID
FROM canadiancrudes c1
WHERE c1.YOURPRIMARYKEY IN (
select MIN(c2.YOURPRIMARYKEY) from canadiancrudes c2 group by c2.BidBroker
)
Replace YOURPRIMARYKEY with your column with your row-unique id.
As others have said, don't use "group by" if you don't want to aggregate something. If you do want to aggregate by one column but include others as well, consider researching "partition."

How do I assign weights to different columns in a full text search?

In my full text search query, I want to assign particular columns a higher weightage. Consider this query:
SELECT Key_Table.RANK, FT_Table.* FROM Restaurants AS FT_Table
INNER JOIN FREETEXTTABLE(Restaurants, *, 'chilly chicken') AS Key_Table
ON FT_Table.RestaurantID = Key_Table.[KEY]
ORDER BY Key_Table.RANK DESC
Now, I want the Name column to have a higher weightage in the results (Name, Keywords and Location are full-text indexed). Currently, if the result is found in any of the three columns, the ranks are not affected.
For example, I'd like a row with Name "Chilly Chicken" to have higher rank than one with Keywords "Chilly Chicken", but another name.
Edit:
I'm not eager to use ContainsTable, because that would mean separating the phrases (Chilly AND Chicken, etc.), which would involve me having to search all possible combinations - Chilly AND Chicken, Chilly OR Chicken, etc. I would like the FTS engine to automatically figure out which results match best, and I think FREETEXT does a fine job this way.
Apologies if I've misunderstood how CONTAINS/CONTAINSTABLE works.
The best solution is to use ContainsTable. Use a union to create a query that searches all 3 columns and adds an integer used to indicate which column was searched. Sort the results by that integer and then rank desc.
The rank is internal to sql server and not something you can adjust.
You could also manipulate the returned rank by dividing the rank by the integer (Name would be divided by 1, Keyword and Location by 2 or higher). That would cause the appearance of different rankings.
Here's some example sql:
--Recommend using start change tracking and start background updateindex (see books online)
SELECT 1 AS ColumnLocation, Key_Table.Rank, FT_Table.* FROM Restaurants AS FT_Table
INNER JOIN ContainsTable(Restaurant, Name, 'chilly chicken') AS Key_Table ON
FT_Table.RestaurantId = Key_Table.[Key]
UNION SELECT 2 AS ColumnLocation, Key_Table.Rank, FT_Table.* FROM Restaurants AS FT_Table
INNER JOIN ContainsTable(Restaurant, Keywords, 'chilly chicken') AS Key_Table ON
FT_Table.RestaurantId = Key_Table.[Key]
UNION SELECT 3 AS ColumnLocation, Key_Table.Rank, FT_Table.* FROM Restaurants AS FT_Table
INNER JOIN ContainsTable(Restaurant, Location, 'chilly chicken') AS Key_Table ON
FT_Table.RestaurantId = Key_Table.[Key]
ORDER BY ColumnLocation, Rank DESC
In a production environment, I would insert the output of the query into a table variable to perform any additional manipulation before returning the results (may not be necessary in this case). Also, avoid using *, just list the columns you really need.
Edit: You're right about using ContainsTable, you would have to modify the keywords to be '"chilly*" AND "chicken*"', I do this using a process that tokenizes an input phrase. If you don't want to do that, just replace every instance of ContainsTable above with FreeTextTable, the query will still work the same.

Resources