I cannot use #field-name in my sphinx query, but I can use #*
I could use the #field-name attribute when querying the test.documents example, but not for another table I have indexed.
This is my PHP:
require_once('sphinxapi.php');
$this->sphinx = new SphinxClient;
$this->sphinx->setServer("localhost", 9312);
$this->sphinx->setMatchMode(SPH_MATCH_EXTENDED2);
//This works:
$result = $this->sphinx->query("#* bob");
var_dump($result);
//This doesn't work:
$result = $this->sphinx->query("#artist bob");
var_dump($result);
Output of: /usr/local/sphinx/bin/indexer --all --rotate --dump-rows sphinxrows.txt
# === source src1 ts 1318588067
# Fri Oct 14 10:27:47 2011
#
# field 0: name
# field 1: filename
# field 2: artist
# sql_attr_uint = id_attr # attr 0
# sql_attr_timestamp = date_added # attr 1
#
DROP TABLE IF EXISTS rows_src1;
CREATE TABLE rows_src1 (
id VARCHAR(32) NOT NULL,
id_attr VARCHAR(4096) NOT NULL,
date_added VARCHAR(4096) NOT NULL,
name VARCHAR(4096) NOT NULL,
filename VARCHAR(4096) NOT NULL,
artist VARCHAR(4096) NOT NULL,
KEY(id) );
INSERT INTO rows_src1 VALUES ('6', '6', '0', 'track 1 title', 'track-1.wav', 'bob');
INSERT INTO rows_src1 VALUES ('70', '70', '0', 'track 2 title', 'track-2.wav', 'eric');
Sphinx.conf:
source src1
{
type = mysql
sql_query = \
SELECT id, id AS id_attr, UNIX_TIMESTAMP(date_added) AS date_added, name, filename, artist \
FROM files
sql_attr_uint = id_attr
sql_attr_timestamp = date_added
sql_query_info = SELECT * FROM files WHERE id=$id
}
In sql you have "rows_src1" table , in sphinx.conf you have "files" as table
Field names need to be defined in sphinx.conf. Adding an entry for "rt_field" solved this for me.
Related
I create a migration to to convert a jsonb column into a one-to-many table.
-- upgrade
insert into device_component (
warranty_request_uuid,
serial_number,
component_type,
description
)
select
warranty_request.uuid,
value->>'serial_number',
value->>'type',
value->>'description'
from
warranty_request,
jsonb_array_elements(warranty_request.device_components)
I need to provide a corresponding downgrade statement. To revert the migration, I am trying something like the below.
-- downgrade
update
warranty_request
set
device_components = jsonb_set(
device_components,
'{}',
jsonb_build_object(
'serial_number', device_component.serial_number,
'type', device_component.component_type,
'description', device_component.description
)
)
from
device_component
where
warranty_request.uuid = device_component.warranty_request_uuid
The problem is that the device_components column contains only null values after downgrading. So nothing is inserted.
How, should the downgrade statement look like to make this work?
I want to upgrade and downgrade between these 2 formats.
Upgrade:
# warranty_request
uuid
-----
abc
# device_compoent
uuid | warranty_request_uuid | serial_number | device_type | description
-----|-----------------------|---------------|-------------|------------
efg | abc | 1 | foo | bar
hij | abc | 2 | foo | bar
Downgrade:
# warranty_request
uuid | device_components
------|----------------------------------------------------------------------------------------------------------------------
abc | [{"serial_number": 1, "type": "foo", "description": bar}, {"serial_number": 2, "type": "foo", "description": bar}]
You can try this :
UPDATE
warranty_request AS w
SET
device_components = a.device_components
FROM
( SELECT d.warranty_request_uuid
, jsonb_agg (jsonb_build_object
( 'serial_number', d.serial_number
, 'type', d.device_type
, 'description', d.description
)
) AS device_components
FROM device_component AS d
GROUP BY d.warranty_request_uuid
) AS a
WHERE w.uuid = a.warranty_request_uuid
see the demo result in dbfiddle.
In SQL Server I have two tables, Registrar Records and Teacher Records which are identical. The first part of the query matches on the student ID and shows whether or not a match was found in a dynamic column (that part I did already).
An additional dynamic column should list out all the columns that didn't match - I'm wondering if there is a way to do this without making a gigantic Case expression since that would have many possibilities, this is what I have so far:
SET ANSI_NULLS OFF
SELECT TR.*,
CASE WHEN RR.StudentID IS NULL THEN 'NO MATCH'
WHEN RR.StudentID IS NOT NULL AND RR.FirstName = TR.FirstName
AND RR.LastName = TR.LastName
AND RR.Floor = TR.Floor
AND RR.FirstQuarterGrade = TR.FirstQuarterGrade
AND RR.SecondQuarterGrade = TR.SecondQuarterGrade
AND RR.ThirdQuarterGrade = TR.ThirdQuarterGrade
AND RR.FinalGrade = TR.FinalGrade THEN 'MATCH'
ELSE 'MATCH WITH ISSUE' END AS MatchResult
--TO DO: Add a ISSUE column; lists columns with mismatch
FROM TeacherRecords TR
LEFT JOIN RegistrarRecords RR ON RR.StudentID = TR.StudentID
If a script is needed for the table here is the table:
CREATE TABLE [dbo].[RegistrarRecords](
[StudentID] [varchar](10) NOT NULL,
[FirstName] [varchar](50) NULL,
[LastName] [varchar](50) NULL,
[Floor] [int] NULL,
[Room] [varchar](10) NULL,
[FirstQuarterGrade] [int] NULL,
[SecondQuarterGrade] [int] NULL,
[ThirdQuarterGrade] [int] NULL,
[FinalGrade] [int] NULL
) ON [PRIMARY]
You could split this query into two parts
First find all the issues
Then check if there are any issues in doing the final select
Here is sample code to do so. The Issue_List field contains a comma-separated list of all the columns with issues (e.g., 'Floor, FirstQuarterGrade'). If this field is empty, then it represents that there are no issues.
WITH TR_Match_Info AS
(SELECT TR.*,
RR.StudentID AS RR_StudentID,
'' + CASE WHEN RR.FirstName = TR.FirstName THEN '' ELSE 'FirstName, ' END
+ CASE WHEN RR.LastName = TR.LastName THEN '' ELSE 'LastName, ' END
+ CASE WHEN RR.Floor = TR.Floor THEN '' ELSE 'Floor, ' END
+ CASE WHEN RR.FirstQuarterGrade = TR.FirstQuarterGrade THEN '' ELSE 'FirstQuarterGrade, ' END
+ CASE WHEN RR.SecondQuarterGrade = TR.SecondQuarterGrade THEN '' ELSE 'SecondQuarterGrade, ' END
+ CASE WHEN RR.ThirdQuarterGrade = TR.ThirdQuarterGrade THEN '' ELSE 'ThirdQuarterGrade, ' END
+ CASE WHEN RR.FinalGrade = TR.FinalGrade THEN '' ELSE 'FinalGrade, ' END
AS Issue_List
FROM TeacherRecords TR
LEFT JOIN RegistrarRecords RR ON RR.StudentID = TR.StudentID
)
SELECT [StudentID],
[FirstName],
[LastName],
[Floor],
[Room],
[FirstQuarterGrade],
[SecondQuarterGrade],
[ThirdQuarterGrade],
[FinalGrade],
CASE WHEN RR_StudentID IS NULL THEN 'NO MATCH'
WHEN Issue_List = '' THEN 'MATCH'
ELSE 'MATCH WITH ISSUE' END
AS MatchResult,
CASE WHEN RR_StudentID IS NULL THEN ''
WHEN LEN(Issue_List) > 0 THEN LEFT(Issue_List, LEN(Issue_List) - 1)
ELSE Issue_List
END AS Match_Issues
FROM TR_Match_Info;
Note that the issue checks above are based on your code. You should review how NULLs are handled - if the values are both NULL it flags it as an issue (e.g., when checking whether NULL = NULL the result is NULL so it goes to the ELSE component of these CASE expressions).
I am trying to fetch the count from SQL server database and it gives 0 for fields with null values. Below is what I am using.
my $sql = q{SELECT count(*) from customer where first_name = ? and last_name = ?};
my #bind_values = ($first_name, $last_name);
my $count = $dbh->selectrow_array($sql, undef, #bind_values);
This returns 0 if either value is null in the database. I know prepare automatically makes it is null if the passed parameter is undef, but I don't know why it's not working.
So here is weird observation. When I type the SQL with values in Toda for SQL server, it works :
SELECT count(*) from customer where first_name = 'bob' and last_name is null
but when I try the same query and pass values in the parameter for the first_name = bob and the last_name {null} . it does not work.
SELECT count(*) from customer where first_name = ? and last_name = ?
For NULL in the WHERE clause you simply need a different query. I write them below each other, so you can spot the difference:
...("select * from test where col2 = ?", undef, 1);
...("select * from test where col2 is ?", undef, undef);
...("select * from test where col2 is ?", undef, 1);
...("select * from test where col2 = ?", undef, undef);
The first two commands work, stick to those. The third is a syntax error, the fourth is what you tried and which indeed does not return anything.
The DBI manpage has a section of NULL values that talks about this case a bit more.
So, here it is what I did. I added or field is null statement with each field if the value is undef.
my $sql = q{SELECT count(*) from customer where (first_name = ? or (first_name is null and ? = 1)) and (last_name = ? or (last_name is null and ? = 1))};
my #bind_values = ($first_name, defined($first_name)?0:1, $last_name, defined($last_name)?0:1);
my $count = $dbh->selectrow_array($sql, undef, #bind_values);
If anyone has better solution please post it.
I am working on migrating data from one database to another for a hospital. In the old database, the doctor's specialty IDs are all in one column (swvar_specialties), each separated by commas. In the new database, each specialty ID will have it's own column (example: Specialty1_PrimaryID, Specialty2_PrimaryID, Specialty3_PrimaryID, etc). I am trying to export the data out of the old database and separate these into these separate columns. I know I can use indexof and substring to do this - I just need help with the syntax.
So this query:
Select swvar_specialties as Specialty1_PrimaryID
From PhysDirectory
might return results similar to 39,52,16. I need this query to display Specialty1_PrimaryID = 39, Specialty2_PrimaryID = 52, and Specialty3_PrimaryID = 16 in the results. Below is my query so far. I will eventually have a join to pull the specialty names from the specialties table. I just need to get this worked out first.
Select pd.ref as PrimaryID, pd.swvar_name_first as FirstName, pd.swvar_name_middle as MiddleName,
pd.swvar_name_last as LastName, pd.swvar_name_suffix + ' ' + pd.swvar_name_degree as NameSuffix,
pd.swvar_birthdate as DateOfBirth,pd.swvar_notes as AdditionalInformation, 'images/' + '' + pd.swvar_photo as ImageURL,
pd.swvar_philosophy as PhilosophyOfCare, pd.swvar_gender as Gender, pd.swvar_specialties as Specialty1_PrimaryID, pd.swvar_languages as Language1_Name
From PhysDirectory as pd
The article Split function equivalent in T-SQL? provides some details on how to use a split function to split a comma-delimited string.
By modifying the table-valued function in presented in this article to provide an identity column we can target a specific row such as Specialty1_PrimaryID:
/*
Splits string into parts delimitered with specified character.
*/
CREATE FUNCTION [dbo].[SDF_SplitString]
(
#sString nvarchar(2048),
#cDelimiter nchar(1)
)
RETURNS #tParts TABLE (id bigint IDENTITY, part nvarchar(2048) )
AS
BEGIN
if #sString is null return
declare #iStart int,
#iPos int
if substring( #sString, 1, 1 ) = #cDelimiter
begin
set #iStart = 2
insert into #tParts
values( null )
end
else
set #iStart = 1
while 1=1
begin
set #iPos = charindex( #cDelimiter, #sString, #iStart )
if #iPos = 0
set #iPos = len( #sString )+1
if #iPos - #iStart > 0
insert into #tParts
values ( substring( #sString, #iStart, #iPos-#iStart ))
else
insert into #tParts
values( null )
set #iStart = #iPos+1
if #iStart > len( #sString )
break
end
RETURN
END
Your query can the utilise this split function as follows:
Select
pd.ref as PrimaryID,
pd.swvar_name_first as FirstName,
pd.swvar_name_middle as MiddleName,
pd.swvar_name_last as LastName,
pd.swvar_name_suffix + ' ' + pd.swvar_name_degree as LastName,
pd.swvar_birthdate as DateOfBirth,pd.swvar_notes as AdditionalInformation,
'images/' + '' + pd.swvar_photo as ImageURL,
pd.swvar_philosophy as PhilosophyOfCare, pd.swvar_gender as Gender,
(Select part from SDF_SplitString(pd.swvar_specialties, ',') where id=1) as Specialty1_PrimaryID,
(Select part from SDF_SplitString(pd.swvar_specialties, ',') where id=2) as Specialty2_PrimaryID,
pd.swvar_languages as Language1_Name
From PhysDirectory as pd
We have a simple model Company. Each company can have one ore more departments Dept. Each department is of a certain type Type.
Now we need a query where all companies are returned, which have a department of type X and one of type Y at least (i.e. each returned company has two or more departments, at least one X and one Y).
How can that be done with a query?
This query gives no results if getTypes returns more than one type.
if (count($types = $demand->getTypes()) > 0) {
foreach ($types as $type)
$constraints[] = $query->contains('dept.type', $type);
}
$result = $query->matching($query->logicalAnd($query->logicalAnd($constraints)))->execute();
This query returns results for type X or Y
if (count($types = $demand->getTypes()) > 0) {
$constraints[] = $query->in('dept.type', $types);
}
The tables look like this (simplified):
CREATE TABLE IF NOT EXISTS `company` (
`uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
PRIMARY KEY (`uid`)
);
CREATE TABLE IF NOT EXISTS `dept` (
`uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
`company` int(10) unsigned NOT NULL,
`type` int(10) unsigned NOT NULL,
PRIMARY KEY (`uid`)
);
CREATE TABLE IF NOT EXISTS `type` (
`uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
PRIMARY KEY (`uid`)
);
if (count($types = $demand->getTypes()) > 0) {
foreach ($types as $type)
$constraints[] = $query->contains('dept.type', $type);
}
You do not show the further processing.
If you need AND operation use this:
$result = $query->matching($query->logicalAnd($query->logicalAnd($constraints)))->execute();
If you need OR operation use this:
$result = $query->matching($query->logicalAnd($query->logicalOr($constraints)))->execute();
HTH
I found out that $query->contains() only works properly with plain _mm tables.
So this is what I did: I just added a view to the DB which has the required fields for a _mm table:
CREATE VIEW `company_type_mm` AS
SELECT
`company` AS `uid_local`,
`type` AS `uid_foreign`,
0 AS `sorting`,
0 AS `sorting_foreign`
FROM `dept`;
Then I added a new field dept to the TCA of the company table:
'type' => array(
...
'config' => array(
'foreign_table' => 'type',
'MM' => 'company_type_mm',
...
)
)
And now I get the right results for companies which have departments of type A and type B like this:
if (count($types = $demand->getTypes()) > 0) {
foreach ($types as $type)
$constraints[] = $query->contains('type', $type);
}