I am trying to list all entries whose names start with the letter 'R' and are older than 20 but It is not working - Can you please give me a hint ?
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT DISTINCT ?givenname ?Age ?firstName
WHERE {
?Person foaf:givenname ?firstName
{FILTER (?Age > '20')}
UNION
{FILTER regex(?givename, "^(R)")}
}
To find names that start with "R", you can use STRSTARTS():
FILTER( STRSTARTS(?givename, "R") ) .
To filter based on the age, you first have to add/bind this variable in a triple pattern, e.g.:
?Person ex:yourAgeProperty ?Age .
Your age FILTER compares strings (as you use quotation marks and don’t specify a datatype, which defaults to xsd:string). In case the age is given as xsd:integer in your data, you could use:
FILTER( ?Age > "20"^^xsd:integer ) .
And if both filters need to apply, simply list them one after the other (without {} and without UNION). Or you could combine them:
FILTER( STRSTARTS(?givename, "R") && ?Age > "20"^^xsd:integer ) .
Related
I am fairly new to Power BI and DAX and I am struggling with getting the below measure to work (I have provided to different version of what I have tried). I am trying to COUNTA the # of items that met certain criteria in two separate columns. Each column that the measure looks at has at least 3 filter criteria and in column two I need to use wildcards as the data there in has entries that share the first two values but the 3rd value could change over time. Any assistance would be amazing as I have tried dozens of different ways and I still cannot figure it out.
GA = CALCULATE(COUNTA(Table,[Item]),filter(Table,Table[Column 1]in{"GA","SP"}) , Filter(Table,Table[Column2]in{"MT*","GA*","SP*","OP*"}))
GA = CALCULATE(COUNTA(Table[Item]),Table[Column1]= "GA" || Table[Column1]= "SP" && Table[Column2]="GA*" || Table[Column2]= "OP*" || Table[Column2]]= "SP*" || Table[Column2]= "MT*")
Unfortunately I cannot provide an example of the data.
Thank you in advance
As #Alexis Olson mentions in his reply to this post, there does not appear to be a shorthand way to use the IN operator with wildcards.
Hence:
GA =
CALCULATE(
COUNTROWS( 'Table' ),
FILTER(
'Table',
'Table'[Column1]
IN { "GA", "SP" }
&& (
CONTAINSSTRING( 'Table'[Column2], "MT" )
|| CONTAINSSTRING( 'Table'[Column2], "GA" )
|| CONTAINSSTRING( 'Table'[Column2], "SP" )
|| CONTAINSSTRING( 'Table'[Column2], "OP" )
)
)
)
In my application I am doing a scope/search on :title for a search/filter of my records. The search itself works fine, only thing is that user need to write exactly the title & they can't search word within the :title.
For instance If the title is: This search is cool, user need to start the search and have the complete sentence: This search to search and they can't write is cool and get records that have is cool in the title.
My scope looks like:
class Post < ActiveRecord::Base
scope :search_query, lambda { |query|
return nil if query.blank?
# condition query, parse into individual keywords
terms = query.downcase.split(/\s+/)
# replace "*" with "%" for wildcard searches,
# append '%', remove duplicate '%'s
terms = terms.map { |e|
(e.gsub('*', '%') + '%').gsub(/%+/, '%')
}
# configure number of OR conditions for provision
# of interpolation arguments. Adjust this if you
# change the number of OR conditions.
num_or_conditions = 1
where(
terms.map {
or_clauses = [
"LOWER(posts.title) LIKE ?"
].join(' OR ')
"(#{ or_clauses })"
}.join(' AND '),
*terms.map { |e| [e] * num_or_conditions }.flatten
)
}
How can I make my scope/query so user can search words within the title and get records that has words they have searched for?
I tried with ILIKE, but then the search stop working in development, I think its because of sqlite can't have ILIKE, but in productionthe search worked but still can't search for words within titles.
When I use LIKE, the sql query was:
SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "posts" WHERE ((LOWER(posts.title) LIKE 'rails%')) LIMIT 50 OFFSET 0) subquery_for_count
While when I used ILIKE, the query was:
SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "posts" WHERE ((LOWER(posts.title) ILIKE 'rails%')) LIMIT 50 OFFSET 0) subquery_for_count
SQLite3::SQLException: near "ILIKE": syntax error: SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "posts" WHERE ((LOWER(posts.title) ILIKE 'rails%')) LIMIT 50 OFFSET 0) subquery_for_count
ps: Im using Filterrific gem
I use pg gem for Production ENV & sqlite3 for Development ENV
As its described in this w3schools article, LIKE works as:
WHERE CustomerName LIKE 'a%' => Finds any values that starts with "a"
WHERE CustomerName LIKE '%a' => Finds any values that ends with "a"
WHERE CustomerName LIKE '%or%' => Finds any values that have "or" in any position
WHERE CustomerName LIKE '_r%' => Finds any values that have "r" in the second position
WHERE CustomerName LIKE 'a_%_%' => Finds any values that starts with "a" and are at least 3 characters in length
WHERE ContactName LIKE 'a%o' => Finds any values that starts with "a" and ends with "o"
I needed to change (e.gsub('*', '%') + '%').gsub(/%+/, '%'), to: ('%' + e.gsub('*', '%') + '%').gsub(/%+/, '%') .
When searching with (e.gsub('*', '%') + '%').gsub(/%+/, '%'), result would be (LOWER(posts.title) ILIKE 'keyword%'), where as ('%' + e.gsub('*', '%') + '%').gsub(/%+/, '%'), would give (LOWER(posts.title) ILIKE '%keyword%')
I'd like to select data property values using sparql with some restrictions on their languages:
I have an ordered set of preferred languages ("ru", "en", ... etc )
If an item have more than one language for value, I'd like to have only one value restricted by my set of languages (if ru is available - I want to see ru value, else if en available I want to see en else if ... etc if no lang available - no lang value).
Current query is:
select distinct ?dataProperty ?dpropertyValue where {
<http://dbpedia.org/resource/Blackmore's_Night> ?dataProperty ?dpropertyValue.
?dataProperty a owl:DatatypeProperty.
FILTER ( langmatches(lang(?dpropertyValue),"ru") || langmatches(lang(? dpropertyValue),"en") || lang(?dpropertyValue)="" )
}
The problem with it: results contain two rows for abstract (ru+en). I want only one row, which should contain ru. In case when ru is not available I'd like to get en etc.
How?
Suppose you have data like this:
#prefix : <http://stackoverflow.com/q/21531063/1281433/> .
:a a :resource;
:p "a in english"#en, "a in russian"#ru .
:b a :resource ;
:p "b in english"#en .
Then you're hoping to get results like this:
--------------------------------
| resource | label |
================================
| :b | "b in english"#en |
| :a | "a in russian"#ru |
--------------------------------
Here are two ways of doing this.
Associate language tags with ranks, find the rank of the best label, then find the label with that rank
This way uses SPARQL 1.1 subqueries, aggregates, and data provided with values. The idea is to use values to associate each language tag with a rank. Then you use a subquery to pull out the optimal rank over all the labels that the resource has). Then in the outer query, you have access to the optimal rank, and you just retrieve the label with the language corresponding to that rank.
prefix : <http://stackoverflow.com/q/21531063/1281433/>
select ?resource ?label where {
# for each resource, find the rank of the
# language of the most preferred label.
{
select ?resource (min(?rank) as ?langRank) where {
values (?lang ?rank) { ("ru" 1) ("en" 2) }
?resource :p ?label .
filter(langMatches(lang(?label),?lang))
}
group by ?resource
}
# ?langRank from the subquery is, for each
# resource, the best preference. With the
# values clause, we get just the language
# that we want.
values (?lang ?langRank) { ("ru" 1) ("en" 2) }
?resource a :resource ; :p ?label .
filter(langMatches(lang(?label),?lang))
}
Select the labels separately and coalesce in the order that you want
You can select an optional label for each of the languages you're considering, and then coalesce them into (so you get the first one that's bound) in the order of your preference. This is kind of verbose, but if you need to do anything else with the labels in various languages other than the most preferred, you'll have access to them.
prefix : <http://stackoverflow.com/q/21531063/1281433/>
select ?resource ?label where {
# find resources
?resource a :resource .
# grab a russian label, if available
optional {
?resource :p ?rulabel .
filter( langMatches(lang(?rulabel),"ru") )
}
# grab an english label, if available
optional {
?resource :p ?enlabel .
filter( langMatches(lang(?enlabel),"en") )
}
# take either as the label, but russian over english
bind( coalesce( ?rulabel, ?enlabel ) as ?label )
}
Given XML file-record like this
<ADR-NSBG>
<timeline timestamp="2011-06-09T00:15:00">
<datum datum="SGC_at_bsNo-14___SignalingNetworkConnection_at_netId-4___Sip_at_networkRole-2">
<sbgSipTotalIncSipRequests>4314320</sbgSipTotalIncSipRequests>
<sbgSipTotalIncSipResponses>9040481</sbgSipTotalIncSipResponses>
<sbgSipTotalIncFailureResponses>2321242</sbgSipTotalIncFailureResponses>
<sbgSipTotalOutSipRequests>9136608</sbgSipTotalOutSipRequests>
<sbgSipTotalOutSipResponses>4643002</sbgSipTotalOutSipResponses>
<sbgSipTotalOutFailureResponses>1027420</sbgSipTotalOutFailureResponses>
<sbgSipIncommingProvisionalResponses>3433875</sbgSipIncommingProvisionalResponses>
<sbgSipOutgoingProvisionalResponses>1845750</sbgSipOutgoingProvisionalResponses>
</datum>
<datum datum="SGC_at_bsNo-13___SignalingNetworkConnection_at_netId-4___Sip_at_networkRole-2">
<sbgSipTotalIncSipRequests>4799739</sbgSipTotalIncSipRequests>
<sbgSipTotalIncSipResponses>9335965</sbgSipTotalIncSipResponses>
<sbgSipTotalIncFailureResponses>2415690</sbgSipTotalIncFailureResponses>
<sbgSipTotalOutSipRequests>9474295</sbgSipTotalOutSipRequests>
<sbgSipTotalOutSipResponses>5291708</sbgSipTotalOutSipResponses>
<sbgSipTotalOutFailureResponses>1149950</sbgSipTotalOutFailureResponses>
<sbgSipIncommingProvisionalResponses>3516298</sbgSipIncommingProvisionalResponses>
<sbgSipOutgoingProvisionalResponses>2190601</sbgSipOutgoingProvisionalResponses>
</datum>
</timeline>
</ADR-NSBG>
What I would like to do is to get the values of the children of the datum element.
so, I have written the following query:
for $i in collection("/db/_DEMO/ADR-NSBG/sipTransactTM/2011/06/09")
let $TIME_FROM := "2011-06-09T00:15:00"
let $TIME_TO := "2011-06-09T00:45:00"
let $DATUM := "SGC_at_bsNo-13___SignalingNetworkConnection_at_netId-4___Sip_at_networkRole-2"
where ( $i/ADR-NSBG/timeline/#timestamp/string(.) >= $TIME_FROM and
$i/ADR-NSBG/timeline/#timestamp/string(.) <= $TIME_TO) and
( $i/ADR-NSBG/timeline/datum/#datum/string(.) = $DATUM )
order by $i/ADR-NSBG/timeline/#timestamp/string(.)
return $i/ADR-NSBG/timeline/datum
But, the problem is that I cannot choose between the two "datum" nodes.
the result of the query is:
<datum datum="SGC_at_bsNo-14___SignalingNetworkConnection_at_netId-4___Sip_at_networkRole-2">
<sbgSipTotalIncSipRequests>4314320</sbgSipTotalIncSipRequests>
<sbgSipTotalIncSipResponses>9040481</sbgSipTotalIncSipResponses>
<sbgSipTotalIncFailureResponses>2321242</sbgSipTotalIncFailureResponses>
<sbgSipTotalOutSipRequests>9136608</sbgSipTotalOutSipRequests>
<sbgSipTotalOutSipResponses>4643002</sbgSipTotalOutSipResponses>
<sbgSipTotalOutFailureResponses>1027420</sbgSipTotalOutFailureResponses>
<sbgSipIncommingProvisionalResponses>3433875</sbgSipIncommingProvisionalResponses>
<sbgSipOutgoingProvisionalResponses>1845750</sbgSipOutgoingProvisionalResponses>
</datum>
<datum datum="SGC_at_bsNo-13___SignalingNetworkConnection_at_netId-4___Sip_at_networkRole-2">
<sbgSipTotalIncSipRequests>4799739</sbgSipTotalIncSipRequests>
<sbgSipTotalIncSipResponses>9335965</sbgSipTotalIncSipResponses>
<sbgSipTotalIncFailureResponses>2415690</sbgSipTotalIncFailureResponses>
<sbgSipTotalOutSipRequests>9474295</sbgSipTotalOutSipRequests>
<sbgSipTotalOutSipResponses>5291708</sbgSipTotalOutSipResponses>
<sbgSipTotalOutFailureResponses>1149950</sbgSipTotalOutFailureResponses>
<sbgSipIncommingProvisionalResponses>3516298</sbgSipIncommingProvisionalResponses>
<sbgSipOutgoingProvisionalResponses>2190601</sbgSipOutgoingProvisionalResponses>
</datum>
What I would like to ask you is : Why the statement ( $i/ADR-NSBG/timeline/datum/#datum/string(.) = $DATUM ) does not work ?
Whithin the where clause you are filtering the $i elements of the for clause by using the datum element. You are not filtering the datum elements.
This expression:
( $i/ADR-NSBG/timeline/datum/#datum/string(.) = $DATUM )
is resolved to:
(
"SGC_at_bsNo-14___SignalingNetworkConnection_at_netId-4___Sip_at_networkRole-2",
"SGC_at_bsNo-13___SignalingNetworkConnection_at_netId-4___Sip_at_networkRole-2"
) =
"SGC_at_bsNo-13___SignalingNetworkConnection_at_netId-4___Sip_at_networkRole-2"
which is true. Therefore, the $i element is selected. After that, the expression in the return clause selects both child elements of the contained timeline element:
$i/ADR-NSBG/timeline/datum
How to filter the datum elements
If you want to select only the datum with a specific string, you need to filter in the return clause:
$i/ADR-NSBG/timeline/datum[#datum eq $DATUM]
I have two entries in my database
Obj1 is tagged with "hello, world, planet"
Obj2 is tagged with "hello"
if I do modelName.tagged_with(["hello", "world", "planet", "earth"], :any=>true)
I want to sort the returned objects in order of highest to lowest number of tags matched.
so in this case i'd like the order to be Obj1, Obj2
how can I do this? is there a way to get number of tags matched for each of the returned results?
You can call tag_list on the objects and use that to figure out how many tags there are:
tags = %w{hello world planet earth}
objs = ModelName.taggedWith(tags, :any => true)
objs.sort_by! { |o| -(tags & o.tag_list).length }
The tags & o.tag_list yields the intersection of the tags you're looking for and the tags found, then we negate the size of the intersection to tell sort_by (which sorts in ascending order) to put larger intersections at the front, negating the result is an easy way to reverse the usual sort order.
Posting this here if someone else is looking for a way to query a model by tags and order by the number of matches. This solution also allows for the usage of any "equality" operator like the % from pg_trgm.
query = <<-SQL
SELECT users.*, COUNT(DISTINCT taggings.id) AS ct
FROM users
INNER JOIN taggings ON taggings.taggable_type = 'User'
AND taggings.context = 'skills'
AND taggings.taggable_id = users.id
AND taggings.tag_id IN
(SELECT tags.id FROM tags
WHERE (LOWER(tags.name) % 'ruby'
OR LOWER(tags.name) % 'java'
OR LOWER(tags.name) % 'sa-c'
OR LOWER(tags.name) % 'c--'
OR LOWER(tags.name) % 'gnu e'
OR LOWER(tags.name) % 'lite-c'
))
GROUP BY users.id
ORDER BY ct DESC;
SQL
User.find_by_sql(query)
Note that the code above will only work if you have pg_trgm enabled. You can also simply replace % with ILIKE.
EDIT: With ActiveRecord and eager loading:
This could be in a scope or class method and can be chained with other ActiveRecord methods.
ActiveRecord::Base.connection
.execute('SET pg_trgm.similarity_threshold = 0.5')
matches = skills.map do
'LOWER(tags.name) % ?'
end.join(' OR ')
select('users.*, COUNT(DISTINCT taggings.id) AS ct')
.joins(sanitize_sql_array(["INNER JOIN taggings
ON taggings.taggable_type = 'User'
AND taggings.context = 'skills'
AND taggings.taggable_id = users.id
AND taggings.tag_id IN
(SELECT tags.id FROM tags WHERE (#{matches}))", *skills]))
.group('users.id')
.order('ct DESC')
.includes(:skills)
Override skill_list from acts-as-taggable-on in the model:
def skill_list
skills.collect(&:name)
end
and proceed normally.