- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 2
SELECT
The SELECT statement.
See APIS ➞
client.query(),table.select()
| Section | Description | 
|---|---|
| Basic Select | Run a basic SELECT query. | 
| The WHEREClause | Specify conditions against which to filter records. | 
| The ORDER BYClause | Sort output rows by specific criteria. | 
| The LIMITClause | Restrict the number of rows returned by a query. | 
| The OFFSETClause | Skip a specified number of rows before returning rows. | 
| The JOINClause | Select records from one table and tie in relevamt records from related tables. | 
| The GROUP BYClause | Group rows together by specific criteria for use with aggregate functions. | 
| The HAVINGClause | Filter groups based on the result of aggregate functions. | 
| The WINDOWClause | Define reusable window specifications for window functions. | 
| Structuring Syntax | Structure your output data without all the rough work. | 
| Magic Paths | Express relationships graphically. | 
Select all fields from all records:
// (a): SQL syntax
const result = await client.query(
    `SELECT *
    FROM public.users`
);// (b): Function-based syntax
const result = await client.database('public').table('users').select();Use the WHERE clause to specify conditions against which to filter records.
Find records that satisfy two specific conditions:
// (a): SQL syntax
const result = await client.query(
    `SELECT *
    FROM public.users
    WHERE name = 'John' AND role = 'guest'`
);// (b): Object-based syntax
const result = await client.database('public').table('users').select(
    { where: [
        { eq: ['name', { value: 'John' }] },
        { eq: ['role', { value: 'guest' }] }
    ] }
);// (c): Function-based syntax
const result = await client.database('public').table('users').select(
    { where: [
        (q) => q.eq('name', (r) => r.value('John')),
        (q) => q.eq('role', (r) => r.value('guest'))
    ] }
);Find records that satisfy a combination of static and dynamic conditions:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        name,
        email
    FROM public.users
    WHERE role IS NOT NULL AND COALESCE(email, phone) IS NOT NULL`
);// (b): Object-based syntax
const result = await client.database('public').table('users').select({
    fields: [ 'name', 'email' ],
    where: [
        { isNotNull: 'role' },
        { isNotNull: { fn: ['COALESCE', 'email', 'phone'] } }
    ]
});// (c): Function-based syntax
const result = await client.database('public').table('users').select({
    fields: [ 'name', 'email' ],
    where: [
        { isNotNull: 'role' },
        { isNotNull: { fn: ['COALESCE', 'email', 'phone'] } }
    ]
});Find records that satisfy a more complex set of conditions:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        name,
        email
    FROM public.users
    WHERE (role = $1 OR role = $2) AND (
        email IS NOT NULL OR (
            phone IS NOT NULL AND country_code IS NOT NULL
        )
    )`
);// (b): Object-based syntax
const result = await client.database('public').table('users').select({
    fields: [ 'name', 'email' ],
    where: [
        { some: [
            { eq: ['role', { binding: 'admin' }] },
            { eq: ['role', { binding: 'contributor' }] }
        ] },
        { some: [
            { isNotNull: 'email' },
            { every: [
                { isNotNull: 'phone' },
                { isNotNull: 'country_code' }
            ] }
        ] }
    ]
});// (c): Function-based syntax
const result = await client.database('public').table('users').select({
    fields: [ 'name', 'email' ],
    where: [
        (q) => q.some(
            (r) => r.eq('role', (s) => s.binding('admin')),
            (r) => r.eq('role', (s) => s.binding('contributor')),
        ),
        (q) => q.some(
            (r) => r.isNotNull('email'),
            (r) => r.every(
                (s) => s.isNotNull('phone'),
                (s) => s.isNotNull('country_code')
            )
        )
    ]
});Use the ORDER BY clause to sort output rows by specific criteria.
Order output rows by a set of dynamic and static criteria:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        name,
        email
    FROM public.users
    ORDER BY
        CASE role WHEN 'admin' THEN 1 WHEN 'contributor' THEN 2 ELSE 3 END ASC,
        CASE WHEN phone IS NULL THEN 0 ELSE 1 END DESC,
        name ASC`
);// (b): Object-based syntax
const result = await client.database('public').table('users').select({
    fields: [ 'name', 'email' ],
    orderBy: [
        { expr: {
            switch: 'role',
            cases: [
                { when: { value: 'admin' }, then: 1 },
                { when: { value: 'contributor' }, then: 2 }
            ],
            default: 0
        }, asc: true },
        { expr: {
            cases: [ { when: { isNull: 'phone' }, then: 0 } ],
            default: 1
        }, desc: true },
        { expr: 'name', asc: true }
    ]
});// (c): Function-based syntax
const result = await client.database('public').table('users').select({
    fields: [ 'name', 'email' ],
    orderBy: [
        (q) => q.expr(
            (r) => r.switch('role').cases(
                (s) => s.when((t) => t.value('admin')).then(1),
                (s) => s.when((t) => t.value('contributor')).then(2)
            ).default(3)
        ).asc(),
        (q) => q.expr(
            (r) => r.cases(
                (s) => s.when((t) => t.isNull('phone')).then(0)
            ).default(1)
        ).desc(),
        (q) => q.expr('name').asc()
    ]
});Use the LIMIT clause to limit the number of rows returned by a query.
Retrieve the first 3 books from the books table:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        title,
        author
    FROM public.books
    LIMIT 3`
);// (b): Function-based syntax
const result = await client.database('public').table('books').select({
    fields: ['title', 'author'],
    limit: 3
});Use the OFFSET clause to skip a specified number of rows before returning rows.
Extend the previous to retrieve the next 3 books after skipping the first 3:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        title,
        author
    FROM public.books
    LIMIT 3 OFFSET 3`
);// (b): Function-based syntax
const result = await client.database('public').table('books').select({
    fields: ['title', 'author'],
    limit: 3,
    offset: 3
});Using the JOIN clause, select records from one table and tie in relevamt records from related tables.
Return a list of books with an extra dimension each: the author's name from the users table:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        books.title,
        books.content,
        usr.name AS author_name
    FROM public.books
    LEFT JOIN public.users AS usr ON books.author = usr.id
    WHERE usr.role = $1`,
    ['admin']
);// (b): Object-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        [ 'books', 'title' ],
        [ 'books', 'content' ],
        { expr: [ 'usr', 'name' ], as: 'author_name' }
    ], leftJoin: {
        expr: ['public', 'users'], as: 'usr', on: [ 
            { eq: [['books', 'author'], ['usr', 'id'] ] } 
        ]
    }, where: [
        { eq: [ [ 'usr', 'role' ], { binding: ['admin'] } ] }
    ] }
);// (c): Function-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        (q) => q.expr([ 'books', 'title' ]),
        (q) => q.expr([ 'books', 'content']),
        (q) => q.expr([ 'usr', 'name' ]).as('author_name'),
    ], leftJoin: (q) => q.expr(['public', 'users']).as('usr').on(
        (r) => r.eq(['books', 'author'], ['usr', 'id'])
    ), where: [
        (q) => q.eq(['usr', 'role'], (r) => r.binding('admin'))
    ] }
);Extend the previous to include another related info: the co-author's name from the users table:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        books.title,
        books.content,
        usr.name AS author_name,
        usr2.name AS coauthor_name
    FROM public.books
    LEFT JOIN public.users AS usr ON books.author = usr.id
    LEFT JOIN public.users AS usr2 ON books.coauthor = usr2.id
    WHERE usr.role = $1`,
    ['admin']
);// (b): Object-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        [ 'books', 'title' ],
        [ 'books', 'content' ],
        { expr: [ 'usr', 'name' ], as: 'author_name' },
        { expr: [ 'usr2', 'name' ], as: 'coauthor_name' }
    ], joins: [
        { type: 'LEFT_JOIN', expr: ['public', 'users'], as: 'usr', on: [ 
            { eq: [['books', 'author'], ['usr', 'id'] ] } 
        ] },
        { type: 'LEFT_JOIN', expr: ['public', 'users'], as: 'usr2', on: [ 
            { eq: [['books', 'coauthor'], ['usr2', 'id'] ] } 
        ] }
    ], where: [
        { eq: [ [ 'usr', 'role' ], { binding: ['admin'] } ] }
    ] }
);// (c): Function-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        (q) => q.expr([ 'books', 'title' ]),
        (q) => q.expr([ 'books', 'content']),
        (q) => q.expr([ 'usr', 'name' ]).as('author_name'),
    ], joins: [
        (q) => q.type('LEFT_JOIN').expr(['public', 'users']).as('usr').on(
            (r) => r.eq(['books', 'author'], ['usr', 'id'])
        ),
        (q) => q.type('LEFT_JOIN').expr(['public', 'users']).as('usr2').on(
            (r) => r.eq(['books', 'coauthor'], ['usr2', 'id'])
        )
    ], where: [
        (q) => q.eq(['usr', 'role'], (r) => r.binding('admin'))
    ] }
);Use the GROUP BY clause to group rows together by specific criteria for use with aggregate functions.
Count the number of books written by each author:
// (a): SQL syntax
const result = await client.query(
    `SELECT author, COUNT(*) AS total_books
    FROM public.books
    GROUP BY author`
);// (b): Object-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        { expr: 'author' },
        { expr: {
            fn: ['COUNT', '*']
        }, as: 'total_books' }
    ], groupBy: ['author'] }
);// (c): Function-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        (q) => q.expr('author'),
        (q) => q.expr(
            (r) => r.fn('COUNT', '*')
        ).as('total_books')
    ], groupBy: ['author'] }
);Use the HAVING clause to filter groups based on the result of aggregate functions.
Limit the results of the previous to only authors with more than 5 books:
// (a): SQL syntax
const result = await client.query(
    `SELECT author, COUNT(*) AS total_books
    FROM public.books
    GROUP BY author
    HAVING COUNT(*) > 5`
);// (b): Object-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        { expr: 'author' },
        { expr: {
            fn: ['COUNT', '*']
        }, as: 'total_books' }
    ], groupBy: ['author'], having: [
        { gt: [{ fn: ['COUNT', '*'] }, 4] }
    ] }
);// (c): Function-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        (q) => q.expr('author'),
        (q) => q.expr(
            (r) => r.fn('COUNT', '*')
        ).as('total_books')
    ], groupBy: ['author'], having: [
        (q) => q.gt((r) => r.fn('COUNT', '*'), 4)
    ] }
);Using the WINDOW clause, define reusable window specifications for window functions, enabling consistent and concise definitions across multiple functions in a query.
Do a little statistics on the books table: for each book, get the daily engagement score on the day book was published:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        title,
        content,
        RANK(num_views ORDER BY content ASC) OVER window_1 AS engagement_score,
    FROM public.books
    WINDOW window_1 AS (
        PARTITION BY created_at
        ORDER BY title ASC
    )`
);// (b): Object-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        { expr: 'title' },
        { expr: 'content' },
        { expr: {
            fn: ['RANK', 'num_views'], over: 'window_1', orderBy: { expr: 'content', asc: true }
        }, as: 'engagement_score' }
    ], window: [
        { name: 'window_1', partitionBy: 'created_at', orderBy: [
            { expr: 'title', asc: true }
        ] }
    ] }
);// (c): Function-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        (q) => q.expr('title'),
        (q) => q.expr('content'),
        (q) => q.expr(
            (r) => r.fn('RANK', 'num_views').over('window_1').orderBy((s) => s.expr('content').asc())
        ).as('engagement_score')
    ], window: [
        (q) => q.name('window_1').partitionBy('created_at').orderBy(
            (r) => r.expr('title').asc()
        )
    ] }
);While you could stitch relevant SQL functions together to structure your output data, Linked QL supports special JSON-like syntaxes that abstract the rough work. (See ➞ JSON Sugars.)
Return output fields in specific formats:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        name,
        phone,
        { email, phone AS mobile } AS contact1,
        [ email, phone ] AS contact2
    FROM public.users`
);// (b): Object-based syntax
const result = await client.database('public').table('users').select({
    fields: [
        { expr: 'name' },
        { expr: 'phone' },
        { expr: {
            fields: ['email', { expr: 'phone', as: 'mobile'}]
        }, as: 'contact1' },
        { expr: {
            items: ['email', 'phone']
        }, as: 'contact2' }
    ]
});// (c): Function-based syntax
const result = await client.database('public').table('users').select({
    fields: [
        (q) => q.expr('name'),
        (q) => q.expr('phone'),
        (q) => q.expr(
            (r) => r.fields('email', (s) => s.expr('phone').as('mobile'))
        ).as('contact1'),
        (q) => q.expr(
            (r) => r.items('email', 'phone')
        ).as('contact2')
    ]
});While you could use the traditional JOIN approach to query relational data, Linked QL supports special path operators that let you express relationships graphically. (See ➞ Magic Paths.)
Return a list of books with an extra dimension each: the author's name from the users table:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        title,
        content,
        author ~> name AS author_name
    FROM public.books
    WHERE author ~> role = $1`,
    ['admin']
);// (b): Object-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        { expr: 'title' },
        { expr: 'content' },
        { expr: {
            path: ['author', '~>', 'name']
        }, as: 'author_name' }
    ], where: [
        { eq: [
            { path: ['author', '~>', 'role'] },
            { binding: ['admin'] }
        ] }
    ] }
);// (c): Function-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        (q) => q.expr('title'),
        (q) => q.expr('content'),
        (q) => q.expr(
            (r) => r.path('author', '~>', 'name')
        ).as('author_name')
    ], where: [
        (q) => q.eq(
            (r) => r.path('author', '~>', 'role'),
            (r) => r.binding('admin')
        )
    ] }
);Extend the previous to include another related info: the co-author's name from the users table:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        title,
        content,
        author ~> name AS author_name,
        coauthor ~> name AS coauthor_name
    FROM public.books
    WHERE author ~> role = $1`,
    ['admin']
);// (b): Object-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        { expr: 'title' },
        { expr: 'content' },
        { expr: {
            path: ['author', '~>', 'name']
        }, as: 'author_name' },
        { expr: {
            path: ['coauthor', '~>', 'name']
        }, as: 'coauthor_name' }
    ], where: [
        { eq: [
            { path: ['author', '~>', 'role'] },
            { binding: ['admin'] }
        ] }
    ] }
);// (c): Function-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        (q) => q.expr('title'),
        (q) => q.expr('content'),
        (q) => q.expr(
            (r) => r.path('author', '~>', 'name')
        ).as('author_name'),
        (q) => q.expr(
            (r) => r.path('coauthor', '~>', 'name')
        ).as('coauthor_name')
    ], where: [
        (q) => q.eq(
            (r) => r.path('author', '~>', 'role'),
            (r) => r.binding('admin')
        )
    ] }
);Return a list of books with an extra dimension each: details of the author:
// (a): SQL syntax
const result = await client.query(
    `SELECT
        title,
        content,
        author: { name, email } AS author
    FROM public.books
    WHERE author ~> role = $1`,
    ['admin']
);// (b): Object-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        { expr: 'title' },
        { expr: 'content' },
        { expr: {
            rpath: ['author', { fields: ['name', 'email'] }]
        }, as: 'author' }
    ], where: [
        { eq: [
            { path: ['author', '~>', 'role'] },
            { binding: ['admin'] }
        ] }
    ] }
);// (c): Function-based syntax
const result = await client.database('public').table('books').select(
    { fields: [
        (q) => q.expr('title'),
        (q) => q.expr('content'),
        (q) => q.expr(
            (r) => r.rpath('author', (s) => s.fields('name', 'email'))
        ).as('author'),
    ], where: [
        (q) => q.eq(
            (r) => r.path('author', '~>', 'role'),
            (r) => r.binding('admin')
        )
    ] }
);