-->

Wikidata+SPARQL: lookup a company based on it'

2020-03-26 12:34发布

问题:

I'm trying to lookup a company based on it's ticker symbol using sparql.

This query will list businesses and their tickers (basic query)

SELECT DISTINCT ?id ?idLabel ?ticker
WHERE {
    ?id wdt:P31/wdt:P279* wd:Q4830453 .
    ?id wdt:P249 ?ticker .
    ?id rdfs:label ?idLabel 
    FILTER(LANG(?idLabel) = 'en').
}

But, IBM is not included, because IBM has it's stock ticker placed 'inside' the P414 property (Stock exchange).

https://www.wikidata.org/wiki/Q37156

How can I expand this list to include companies with P414 and P249 tickers "inside" them?

Here is how I can show ibm is not included:

SELECT DISTINCT ?id ?idLabel ?exchange ?ticker2
WHERE {
    ?id wdt:P31/wdt:P279* wd:Q4830453 .
    ?id wdt:P249 ?ticker . FILTER(LCASE(STR(?ticker)) = 'ibm') .
    ?id rdfs:label ?idLabel 
    FILTER(LANG(?idLabel) = 'en').
}

回答1:

So the answer based on AKSW and Stanislav's comments are that THIS query will list all the stocks on the New York Stock Exchange (as long as the ticker is listed 'under' the exchange:

SELECT DISTINCT ?id ?idLabel ?exchange ?ticker
WHERE {
    ?id wdt:P31/wdt:P279* wd:Q4830453 .
    ?id p:P414 ?exchange . 
    ?exchange ps:P414 wd:Q13677 .
    ?exchange pq:P249 ?ticker .

    ?id rdfs:label ?idLabel 
    FILTER(LANG(?idLabel) = 'en').
}

And THIS query will find a specific stock (IBM) on the New York stock exchange:

SELECT DISTINCT ?id ?idLabel ?exchange ?ticker
WHERE {
    ?id wdt:P31/wdt:P279* wd:Q4830453 .
    ?id p:P414 ?exchange . 
    ?exchange ps:P414 wd:Q13677 .
    ?exchange pq:P249 ?ticker . FILTER(LCASE(STR(?ticker)) = 'ibm') .

    ?id rdfs:label ?idLabel 
    FILTER(LANG(?idLabel) = 'en').
}

And THIS query will find a specific stock on ANY stock exchange, OR referenced directly (Shown here with two different stock tickers to illustrate the search). This query is quite long because wikidata sometimes have the stock exchange sub field UNDER the ticker, and sometimes the other way around. Oh, and sometimes they are two different fields altogether (not linked). Oh Joy.

SELECT DISTINCT ?id ?idLabel ?exchange ?exchangeLabel ?ticker
WHERE {
    ?id wdt:P31/wdt:P279* wd:Q4830453 .
    { 
       # Find cases where the ticker is the main attribute, and the exchange may be below it.
       ?id wdt:P249 ?ticker . FILTER(LCASE(STR(?ticker)) = 'nsu') .
       ?id p:P249 ?tickersub .
       ?tickersub pq:P414 ?exchange 
    }
    UNION {
       # Find the exchange and it's ticker 
       ?id wdt:P414 ?exchange . 
       ?id p:P414 ?exchangesub .
       ?exchangesub pq:P249 ?ticker . FILTER(LCASE(STR(?ticker)) = 'ibm') .
    } 
    UNION {
       # Find the exchange and it's ticker 
       ?id wdt:P414 ?exchange . 
       ?id wdt:P249 ?ticker . FILTER(LCASE(STR(?ticker)) = 'frme') .
    } 
    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}