React-native实现联系人列表分组组件_recipient list 如何分组-程序员宅基地

技术标签: react.js  react  react native  

React-native实现联系人列表分组组件(支持拼音搜索)

参考资料:

React Native使用SectionList打造城市选择列表,包含分组的跳转:https://blog.csdn.net/sinat_17775997/article/details/71424324?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-5&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-5

一. 功能特性和效果图
功能特性如下:

  • 支持首字母和首个汉字分组检索。

  • 支持右侧分组字母的跳转控制。

  • 支持拼音搜索。

  • 支持批量选择功能、重置功能。

效果图:

二. 技术要点

  1. SectionList列表分组组件。
  • https://reactnative.cn/docs/sectionlist
  1. pinyin。 这是一个JS拼音工具开源库。
  • 它的用途是将中文转化为拼音。

  • https://github.com/hotoo/pinyin

三. 实现思路

  1. 将联系人列表中的数据项转化为拼音存储,以便于拼音搜索。

  2. 遍历联系人列表,获取字母分组,得到一个set集合,并且转化为数组,该数组用于渲染右侧字母导航组件。

  3. 构建SectionList组件渲染数据所需要的列表数据结构,其数组元素结构为:{title:‘分组名称’,data:[]},其中,title表示分组名称,data表示该分组的数据列表。

遍历遍历联系人列表,根据首字母分组汇总,得到SectionList组件渲染数据所需要的列表数据结构。

四. 关键代码

  1. 将联系人列表中的数据项转化为拼音存储,以便于拼音搜索。

componentWillMount = () => {
// 将数据列表转化为拼音存储,以便于拼音搜索
testData.forEach((item, index, arr) => {
// 将Item的名称转为拼音数组
let pinyinArr = pinyin(item.name, {style: pinyin.STYLE_NORMAL});
item.pinyinArr = pinyinArr;
let pinyinArrStr = ‘’;
// 将拼音数组转化为一个字符串,以支持拼音搜索
for (let i = 0; i < pinyinArr.length; i++) {
for (let j = 0; j < pinyinArr[i].length; j++) {
pinyinArrStr = pinyinArrStr + pinyinArr[i][j];
}
}
item.pinyinArrStr = pinyinArrStr;
});
this.transferToSectionsData(testData);
};
2. 搜索方法

search = () => {
// alert(‘搜索’);
const {dataList, searchValue} = this.state;
if (searchValue && searchValue.trim()) {
let searchValueTemp = searchValue.toLocaleLowerCase();
const resultList = [];
dataList.forEach((item, index, arr) => {
if (item.name) {
if (item.name.toLocaleLowerCase().indexOf(searchValueTemp) >= 0
|| this.pinyinSingleLetterIndexSearch(searchValueTemp, item.pinyinArr) >= 0
|| item.pinyinArrStr.toLocaleLowerCase().indexOf(searchValueTemp) >= 0) {
resultList.push(item);
}
}
});
console.log(‘search.resultList:’, resultList);
this.transferToSectionsData(resultList);
} else {
this.transferToSectionsData(dataList);
}
};

/**
 * 在拼音数组中搜索单个拼音,如果匹配,则返回等于大于0的值,否则返回-1
 * @param keyword
 * @param pinyinArr
 * @returns {number}
 */
pinyinSingleLetterIndexSearch = (keyword, pinyinArr) => {
    let result = -1;
    if (keyword && pinyinArr) {
        for (let i = 0; i < pinyinArr.length; i++) {
            for (let j = 0; j < pinyinArr[i].length; j++) {
                let singleLetterIndex = pinyinArr[i][j].toLocaleLowerCase().indexOf(keyword);
                if (singleLetterIndex >= 0) {
                    return singleLetterIndex;
                }
            }
        }
    }
    return result;
};

五. 完整代码
注意:图片资源需自行补充。

/**
*

  • @author chenlw
  • @date 2020/04/18
    */
    import React from ‘react’;
    import {
    Dimensions,
    FlatList,
    SectionList,
    StyleSheet,
    Text,
    TouchableOpacity,
    View,
    SafeAreaView,
    Image,
    TextInput,
    Platform,
    StatusBar,
    } from ‘react-native’;

import pinyin from ‘pinyin’;

let testData = [
{id: ‘盖伦’, name: ‘盖伦’},
{id: ‘崔丝塔娜’, name: ‘崔丝塔娜’},
{id: ‘大发明家’, name: ‘大发明家’},
{id: ‘武器大师’, name: ‘武器大师’},
{id: ‘刀妹’, name: ‘刀妹’},
{id: ‘卡特琳娜’, name: ‘卡特琳娜’},
{id: ‘盲僧’, name: ‘盲僧’},
{id: ‘蕾欧娜’, name: ‘蕾欧娜’},
{id: ‘拉克丝’, name: ‘拉克丝’},
{id: ‘剑圣’, name: ‘剑圣’},
{id: ‘赏金’, name: ‘赏金’},
{id: ‘发条’, name: ‘发条’},
{id: ‘瑞雯’, name: ‘瑞雯’},
{id: ‘提莫’, name: ‘提莫’},
{id: ‘卡牌’, name: ‘卡牌’},
{id: ‘剑豪’, name: ‘剑豪’},
{id: ‘琴女’, name: ‘琴女’},
{id: ‘木木’, name: ‘木木’},
{id: ‘雪人’, name: ‘雪人’},
{id: ‘安妮’, name: ‘安妮’},
{id: ‘薇恩’, name: ‘薇恩’},
{id: ‘小法师’, name: ‘小法师’},
{id: ‘艾尼维亚’, name: ‘艾尼维亚’},
{id: ‘奥瑞利安索尔’, name: ‘奥瑞利安索尔’},
{id: ‘布兰德’, name: ‘布兰德’},
{id: ‘凯特琳’, name: ‘凯特琳’},
{id: ‘虚空’, name: ‘虚空’},
{id: ‘机器人’, name: ‘机器人’},
{id: ‘挖掘机’, name: ‘挖掘机’},
{id: ‘EZ’, name: ‘EZ’},
{id: ‘暴走萝莉’, name: ‘暴走萝莉’},
{id: ‘艾克’, name: ‘艾克’},
{id: ‘波比’, name: ‘波比’},
{id: ‘赵信’, name: ‘赵信’},
{id: ‘牛头’, name: ‘牛头’},
{id: ‘九尾’, name: ‘九尾’},
{id: ‘菲兹’, name: ‘菲兹’},
{id: ‘寒冰’, name: ‘寒冰’},
{id: ‘猴子’, name: ‘猴子’},
{id: ‘深渊’, name: ‘深渊’},
{id: ‘凯南’, name: ‘凯南’},
{id: ‘诺克萨斯’, name: ‘诺克萨斯’},
{id: ‘祖安’, name: ‘祖安’},
{id: ‘德莱文’, name: ‘德莱文’},
{id: ‘德玛西亚王子’, name: ‘德玛西亚王子’},
{id: ‘豹女’, name: ‘豹女’},
{id: ‘皮城执法官’, name: ‘皮城执法官’},
{id: ‘泽拉斯’, name: ‘泽拉斯’},
{id: ‘岩雀’, name: ‘岩雀’},
];
const selectedFieldName = ‘id’;

const isAndroid = Platform.OS === ‘android’;
export default class IndexListComponentExample extends React.PureComponent {

constructor(props) {
    super(props);
    this.state = {
        searchValue: null,

        dataList: testData,
        sections: [],       //section数组
        // letterArr: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'],      //首字母数组
        letterArr: [],      //首字母数组
        activeLetterIndex: 0,
        selectedItemSet: new Set(),

        // 是否开启批量选择模式
        batchSelected: true,
        refreshCount: 0,
    };
}

componentWillMount = () => {
    // 将数据列表转化为拼音存储,以便于拼音搜索
    testData.forEach((item, index, arr) => {
        // 将Item的名称转为拼音数组
        let pinyinArr = pinyin(item.name, {style: pinyin.STYLE_NORMAL});
        item.pinyinArr = pinyinArr;
        let pinyinArrStr = '';
        // 将拼音数组转化为一个字符串,以支持拼音搜索
        for (let i = 0; i < pinyinArr.length; i++) {
            for (let j = 0; j < pinyinArr[i].length; j++) {
                pinyinArrStr = pinyinArrStr + pinyinArr[i][j];
            }
        }
        item.pinyinArrStr = pinyinArrStr;
    });
    this.transferToSectionsData(testData);
};

/**
 * 转化数据列表
 */
transferToSectionsData = (dataList) => {
    //获取联系人列表
    let sections = [], letterArr = [];
    // 右侧字母栏数据处理
    dataList.forEach((item, index, arr) => {
        let itemTemp = pinyin(item.name.substring(0, 1), {
            style: pinyin.STYLE_FIRST_LETTER,
        })[0][0].toUpperCase();
        letterArr.push(itemTemp);
    });
    letterArr = [...new Set(letterArr)].sort();
    this.setState({letterArr: letterArr});

    // 分组数据处理
    letterArr.forEach((item, index, arr) => {
        sections.push({
            title: item,
            data: [],
        });
    });

    dataList.forEach((item1, index1, arr1) => {
        let listItem = item1;
        sections.forEach((item2, index2, arr2) => {
            let firstName = listItem.name.substring(0, 1);
            let firstLetter = pinyin(firstName, {style: pinyin.STYLE_FIRST_LETTER})[0][0].toUpperCase();
            let pinyinStrArr = pinyin(listItem.name, {style: pinyin.STYLE_NORMAL});
            console.log('pinyinStr', pinyinStrArr);
            if (item2.title === firstLetter) {
                item2.data.push({
                    firstName: firstName,
                    name: listItem.name,
                    id: listItem.id,
                });
            }
        });
    });
    this.setState({sections: sections});
};

openBatchSelectedMode = (callback) => {
    this.setState({
        batchSelected: true,
        selectedItemSet: new Set(),
    }, () => {
        callback && callback();
    });
};

closeBatchSelectedMode = () => {
    this.setState({
        batchSelected: false,
        selectedItemSet: new Set(),
    });
};

addOrDeleteSelectedItem = (item) => {
    const {batchSelected, selectedItemSet, refreshCount} = this.state;
    if (!batchSelected) {
        return;
    }
    if (item && item[selectedFieldName]) {
        if (selectedItemSet.has(item[selectedFieldName])) {
            selectedItemSet.delete(item[selectedFieldName]);
        } else {
            selectedItemSet.add(item[selectedFieldName]);
        }
        console.log('addOrDeleteSelectedItem.selectedItemSet', selectedItemSet);
        this.setState({
            selectedItemSet: selectedItemSet,
            refreshCount: refreshCount + 1,
        }, () => {

        });
    }
};

/**
 * 重置选中的成员
 */
clearSelectedItem = () => {
    const {batchSelected, selectedItemSet, refreshCount} = this.state;
    selectedItemSet.clear();
    this.setState({
        selectedItemSet: selectedItemSet,
        refreshCount: refreshCount + 1,
    }, () => {

    });
};


// 字母关联分组跳转
_onSectionselect = (key) => {
    this.setState({
        activeLetterIndex: key,
    }, () => {

    });
    this.refs._sectionList.scrollToLocation({
        itemIndex: 0,
        sectionIndex: key,
        viewOffset: 20,
    });

};

// 分组列表的头部
_renderSectionHeader(sectionItem) {
    const {section} = sectionItem;
    return (
        <View style={
   {
            height: 20,
            backgroundColor: '#e7f0f9',
            paddingHorizontal: 10,
            flexDirection: 'row',
            alignItems: 'center',
        }}>
            <Text style={
   {fontSize: 16}}>{section.title.toUpperCase()}</Text>
        </View>
    );
}

renderItemSelectedIcon = (item) => {
    if (!item) {
        return;
    }
    const {batchSelected, selectedItemSet} = this.state;
    if (batchSelected) {
        let isActive = selectedItemSet.has(item[selectedFieldName]);
        return (
            <Image
                style={
   {
                    width: 18,
                    height: 18,
                    marginRight: 10,
                }}
                source={isActive
                    ? require('@assets/icons/common/icon_item_selected.png')
                    : require('@assets/icons/common/icon_item_unselected.png')}
            />
        );
    } else {
        return null;
    }
};

_renderItem(item, index) {
    const {batchSelected} = this.state;
    return (
        <TouchableOpacity
            style={
   {
                paddingLeft: 20,
                paddingRight: 30,
                height: 50,
                flexDirection: 'row',
                justifyContent: 'flex-start',
                alignItems: 'center',
                borderBottomWidth: 1,
                borderBottomColor: '#efefef',
            }}
            activeOpacity={.75}
            onLongPress={() => {
                if (!batchSelected) {
                    this.openBatchSelectedMode(() => {
                        this.addOrDeleteSelectedItem(item);
                    });
                }
            }}
            onPress={() => {
                this.addOrDeleteSelectedItem(item);
            }}
        >
            {
                this.renderItemSelectedIcon(item)
            }
            <View style={
   {
                flexDirection: 'row',
                alignItems: 'center',
                // justifyContent: 'space-between',
                flexGrow: 1,
            }}>
                <View style={
   {
                    // padding: 10,
                    height: 30,
                    width: 30,
                    justifyContent: 'center',
                    alignItems: 'center',
                    backgroundColor: '#2988FF',
                }}>
                    <Text style={
   {
                        color: '#fff',
                        fontSize: 18,
                    }}>
                        {item.firstName}
                    </Text>
                </View>
                <View style={
   {
                    marginLeft: 10,
                }}>
                    <Text style={
   {}}>{item.name}</Text>
                </View>
            </View>
        </TouchableOpacity>
    );
}

renderBatchSelectedHeader = () => {
    const {batchSelected, selectedItemSet} = this.state;
    if (!batchSelected) {
        return (
            <View style={
   {
                paddingLeft: 10,
                paddingRight: 10,
                height: 50,
                flexDirection: 'row',
                justifyContent: 'space-between',
                alignItems: 'center',
                borderBottomWidth: 1,
                borderBottomColor: '#efefef',
            }}>
                <TouchableOpacity
                    style={
   {
                        padding: 10,
                    }}
                >
                </TouchableOpacity>
                <View style={
   {}}>
                </View>
                <TouchableOpacity
                    style={
   {
                        padding: 10,
                    }}
                    onPress={() => {
                        this.openBatchSelectedMode();
                    }}
                >
                    <Text>批量选择</Text>
                </TouchableOpacity>
            </View>
        );
    }
    return (
        <View style={
   {
            paddingLeft: 10,
            paddingRight: 10,
            height: 50,
            flexDirection: 'row',
            justifyContent: 'space-between',
            alignItems: 'center',
        }}>
            <TouchableOpacity
                style={
   {
                    padding: 10,
                }}
                onPress={() => {
                    this.closeBatchSelectedMode();
                }}
            >
                <Text>取消</Text>
            </TouchableOpacity>
            <View style={
   {}}>
                <Text>已选择{selectedItemSet.size}条记录</Text>
            </View>
            <TouchableOpacity
                style={
   {
                    padding: 10,
                }}
                onPress={() => {
                    this.closeBatchSelectedMode();
                }}
            >
                <Text>确定</Text>
            </TouchableOpacity>
        </View>
    );
};


render = () => {
    const {letterArr, sections, activeLetterIndex, batchSelected} = this.state;
    //偏移量 = (设备高度 - 字母索引高度 - 底部导航栏 - 顶部标题栏 - 24)/ 2
    let top_offset = (Dimensions.get('window').height - letterArr.length * 16 - 52 - 44 - 24) / 2;
    if (isAndroid) {
        top_offset = top_offset + StatusBar.currentHeight + 45;
    }
    return (
        <SafeAreaView style={
   {
            flex: 1,
        }}>
            {
                this.renderSearchBar()
            }
            {
                this.renderBatchSelectedHeader()
            }
            <SectionList
                ref="_sectionList"
                renderItem={({item, index}) => this._renderItem(item, index)}
                renderSectionHeader={this._renderSectionHeader.bind(this)}
                sections={sections}
                keyExtractor={(item, index) => item + index}
                ItemSeparatorComponent={() => <View/>}
            />

            {/*右侧字母栏*/}
            <View style={
   {position: 'absolute', width: 26, right: 0, top: top_offset}}>
                <FlatList
                    data={letterArr}
                    keyExtractor={(item, index) => index.toString()}
                    renderItem={({item, index}) => {
                        let isActive = index === activeLetterIndex;
                        // let textStyle = isActive ? styles.activeIndicatorText : styles.inactiveIndicatorText;
                        // let containerStyle = isActive ? styles.activeIndicatorContainer : styles.inactiveIndicatorContainer;
                        let textStyle = styles.inactiveIndicatorText;
                        let containerStyle = styles.inactiveIndicatorContainer;
                        return (
                            <TouchableOpacity
                                style={[
                                    {
                                        marginVertical: 2,
                                        height: 16,
                                        width: 16,
                                        borderRadius: 8,
                                        flexDirection: 'row',
                                        justifyContent: 'center',
                                        alignItems: 'center',
                                    },
                                    containerStyle,
                                ]}
                                onPress={() => {
                                    this._onSectionselect(index);
                                }}
                            >
                                <Text style={[{
                                    fontSize: 12,
                                }, textStyle]}>
                                    {item.toUpperCase()}
                                </Text>
                            </TouchableOpacity>
                        );
                    }}
                />
            </View>

        </SafeAreaView>
    );
};

setSearchValue = (searchValue, callback) => {
    this.setState({
        searchValue: searchValue,
    }, () => {
        callback && callback();
    });
};

search = () => {
    // alert('搜索');
    const {dataList, searchValue} = this.state;
    if (searchValue && searchValue.trim()) {
        let searchValueTemp = searchValue.toLocaleLowerCase();
        const resultList = [];
        dataList.forEach((item, index, arr) => {
            if (item.name) {
                if (item.name.toLocaleLowerCase().indexOf(searchValueTemp) >= 0
                    || this.pinyinSingleLetterIndexSearch(searchValueTemp, item.pinyinArr) >= 0
                    || item.pinyinArrStr.toLocaleLowerCase().indexOf(searchValueTemp) >= 0) {
                    resultList.push(item);
                }
            }
        });
        console.log('search.resultList:', resultList);
        this.transferToSectionsData(resultList);
    } else {
        this.transferToSectionsData(dataList);
    }
};

/**
 * 在拼音数组中搜索单个拼音,如果匹配,则返回等于大于0的值,否则返回-1
 * @param keyword
 * @param pinyinArr
 * @returns {number}
 */
pinyinSingleLetterIndexSearch = (keyword, pinyinArr) => {
    let result = -1;
    if (keyword && pinyinArr) {
        for (let i = 0; i < pinyinArr.length; i++) {
            for (let j = 0; j < pinyinArr[i].length; j++) {
                let singleLetterIndex = pinyinArr[i][j].toLocaleLowerCase().indexOf(keyword);
                if (singleLetterIndex >= 0) {
                    return singleLetterIndex;
                }
            }
        }
    }
    return result;
};

renderSearchBar = () => {
    const {searchValue} = this.state;
    return (
        <View style={
   {
            flexDirection: 'row',
            alignItems: 'center',
            paddingTop: 10,
            paddingBottom: 10,
            backgroundColor: '#fff',
            borderBottomWidth: 1,
            borderBottomColor: '#efefef',
        }}>
            <TouchableOpacity
                style={
   {
                    paddingLeft: 15,
                    paddingRight: 15,
                }}
                onPress={() => {

                }}
            >
                <Image source={require('@assets/icons/common/icon_back.png')}/>
            </TouchableOpacity>
            <View
                style={
   {
                    flex: 1,
                }}
            >
                <View style={
   {
                    height: 30,
                    backgroundColor: '#F0F0F0',
                    borderRadius: 30,
                    paddingLeft: 10,
                    flexDirection: 'row',
                    alignItems: 'center',
                    justifyContent: 'center',
                }}>
                    <Image source={require('@assets/icons/common/icon_search.png')}
                           style={
   {width: 15, height: 15}}/>
                    <TextInput
                        placeholder="输入查询内容..."
                        maxLength={100}
                        style={
   {
                            flex: 1,
                            marginLeft: 5,
                            marginRight: 5,
                            paddingTop: 5,
                            paddingBottom: 5,
                            paddingRight: 5,
                            // backgroundColor: 'pink',
                        }}
                        autoFocus={false}
                        value={searchValue}
                        onChangeText={(text) => {
                            this.setSearchValue(text, () => {
                                this.search();
                            });
                        }}
                        onSubmitEditing={() => {

                        }}
                    />
                    {
                        searchValue
                            ? <TouchableOpacity
                                style={
   {
                                    marginRight: 10,
                                }}
                                onPress={() => {
                                    this.setSearchValue(null, () => {
                                        this.search();
                                    });
                                }}
                            >
                                <Image source={require('@assets/icons/common/icon_search_cancel.png')}
                                       style={
   {
                                           width: 17,
                                           height: 17,
                                       }}
                                />
                            </TouchableOpacity>
                            : null
                    }
                </View>

            </View>
            <TouchableOpacity
                style={
   {
                    paddingLeft: 10,
                    paddingRight: 10,
                    justifyContent: 'center',
                    alignItems: 'center',
                }}
                onPress={() => {
                    this.search();
                }}
            >
                <Text style={
   {
                    color: '#2988FF',
                    fontSize: 16,
                }}>
                    搜索
                </Text>
            </TouchableOpacity>
        </View>
    );
};

}

const styles = StyleSheet.create({
taskNodeTitleText: {
color: ‘#333333’,
fontWeight: ‘bold’,
fontSize: 16,
},
inactiveIndicatorContainer: {},
activeIndicatorContainer: {
backgroundColor: ‘#2988FF’,
},
inactiveIndicatorText: {
color: ‘#666666’,
},
activeIndicatorText: {
color: ‘#fff’,
},
});

————————————————
版权声明:本文为CSDN博主「举世武双」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33721382/article/details/106007853

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dly15873944157/article/details/120677872

智能推荐

工程数学基础 考试 要点 复习:矩阵论,数值计算_工程矩阵论期中考试-程序员宅基地

文章浏览阅读737次。v向量的1-范数∥x∥1=∑k=1n∣ξk∣\|x\|_1=\sum_{k=1}^n|\xi_k|∥x∥1​=∑k=1n​∣ξk​∣向量的2-范数∥x∥2=(∑k=1n∣ξk∣2)12\|x\|_2=(\sum_{k=1}^n|\xi_k|^2)^\frac12∥x∥2​=(∑k=1n​∣ξk​∣2)21​向量的\infty-范数∥x∥∞=max⁡1≤k≤n∣ξk∣\|x\|_\infty=\max_{1\leq k \leq n}|\xi_k|∥x∥∞​=max1≤k≤n​∣ξk​∣列范数=_工程矩阵论期中考试

opencsv解析CSV文件_opencsv 读取csv-程序员宅基地

文章浏览阅读1k次。opencsv解析CSV文件_opencsv 读取csv

2024年【N1叉车司机】考试题库及N1叉车司机考试资料-程序员宅基地

文章浏览阅读670次,点赞16次,收藏10次。47、【多选题】《安全生产法》规定,生产经营单位的决策机构、主要负责人或者个人经营的投资人不依照《安全生产法》规定保证安全生产所必需的资金投入,致使生产经营单位不具备安全生产条件的,责令限期改正,提供必需的资金;逾期未改正的,责令生产经营单位停产停业整顿。39、【单选题】特种设备生产、经营、使用单位应当遵守《中华人民共和国特种设备安全法》和其他有关法律、法规,建立、健全特种设备安全和节能责任制度,加强特种设备安全和节能管理,确保特种设备生产、经营、使用安全,符合()要求。事故原因分析:()( B )

安装和初步使用 nn-Meter_nn-meter部署-程序员宅基地

文章浏览阅读396次。安装和初步使用 nn-Meter_nn-meter部署

消息队列RabbitMQ介绍和使用_rabbitmq消费端 使用 class-程序员宅基地

文章浏览阅读634次。消息队列RabbitMQ介绍和使用_rabbitmq消费端 使用 class

MySQL_DQL语句(分组,筛选)_数据库的备份/还原/约束_mysql备份筛选数据-程序员宅基地

文章浏览阅读118次。DQL语句之分组查询:group byselect 字段列表 from 表名 group by 分组字段名称;注意事项:1) 查询的字段列表中可以使用 分组字段 ;2) group by之后不能使用聚合函数 ;3) 带条件分组查询的语法: where 条件必须放在group by 之前,否则语法错误! ;4) select 字段列表包含分组字段,聚合函数.. from 表名 where 条件 group by 分组字段 ;DQL语句之筛选查询:havingselect 字段列_mysql备份筛选数据

随便推点

微软 Microsoft 面试 要求 资格-程序员宅基地

文章浏览阅读3.2k次。微软亚洲研究院“明日之星”实习生项目硬件计算组招聘实习生Position: Full-time Intern Group: Hardware Computing Group, Microsoft Research AsiaQuantity: 1Work Location: Beijing Project IntroductionMobile Augmented Real..._stars of tomorrow msra

打开 IOS开发者模式_ios17.3开发者模式怎么打开-程序员宅基地

文章浏览阅读1.4k次,点赞2次,收藏2次。需要1、辅助设备:苹果电脑;2、辅助应用:Xcode;3、准备工作:苹果手机使用数据线连接苹果电脑;_ios17.3开发者模式怎么打开

1024 程序员日,全年最大红包,小小心意请笑纳~-程序员宅基地

文章浏览阅读583次。有这么一群神奇的生物:他们喝的是咖啡,挤的是代码……他们总会被黑无趣,却致力于让世界变得有趣……他们靠技术吃饭,但大多数人只关注他们的服装和发量……他们的名字是:程序员转眼 1024 程..._程序员节红包

抖音快手小动画推广项目变现,从快手小游戏到多平台多种形式变现-程序员宅基地

文章浏览阅读180次。快手小游戏推广从二月份的微光计划,大力扶持到现在的对游戏号要求逐步提升,对于视频质量和游戏号粉丝也要求越来越高了,不像之前零粉丝就会给你投放粉条助推。在分享之前先简单说一下我对短视频这个领域这段时间的感悟,最好在某个细分领域深耕,专研贯通后再多平台探索同一个板块会更容易一些。

动态规划之0-1背包问题_0-1背包满足最优子结构特性-程序员宅基地

文章浏览阅读940次。问题描述 0−1背包问题是应用动态规划设计求解的典型例题 已知n种物品和一个可容纳c重量的背包,物品i的重量为w[i],产生的效益为p[i]。在装包时物品i可以装入,也可以不装,但不可拆开装。 问如何装包,所得装包总效益最大。算法分析 最优子结构特性 0−1背包的最优解具有最优子结构特性。 与一般背包问题不同,0−1背包问题要求 即物品i不能折开,或者整体装入,或者不装。当约定每件物品_0-1背包满足最优子结构特性

Hybrid移动应用在多页面大数据复杂业务背景下的优化实践方案_hybrid 大数据-程序员宅基地

文章浏览阅读2.7k次。前言对于混合应用而言,性能问题一直被吐槽,虽然设备的内存的不断增大,很大程度上缓解了这个一问题,但是和原生应用来讲还是有很大区别,本人从Phonegap2.x开始,一直的探索和使用混合应用技术。当时的2.x性能真是不怎么样,首次加载时间也比较长,后来phonegap被apache纳入旗下以后,更名为Cordova,可以说从此以后,性能问题得到了很大的改善,占用内存也越来越小,到如今使用的版本已经变为_hybrid 大数据

推荐文章

热门文章

相关标签